Skip to content

Commit

Permalink
measureIQ calls added in GNIRS and F2 QA recipes, autoredux changes (#…
Browse files Browse the repository at this point in the history
…411)

* F2/GNIRS LS Spect work/autoredux updates to support them

* adding SECTION constant and passing down to avoid doublepeak issues for certain F2

* ensuring text widgets get initialized on creation, needed for apertures interactive (found during work)

* fix AstroDataF2.camera() logic to not require pixel_scale() (so it works on 1D spectra)

* pulled F2 camera fix from CS, simplifying paths for 1D requests for 2D functionality to return None

* inverted section parsing logic to clean things up

* handling None string in Section parse

* removing imports that are no longer needed
  • Loading branch information
olyoberdorf committed Dec 29, 2022
1 parent f1f0a60 commit 077a330
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 14 deletions.
3 changes: 3 additions & 0 deletions astrodata/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ def from_shape(value):
@staticmethod
def from_string(value):
"""The inverse of __str__, produce a Section object from a string"""
# if we were sent None, return None
if value is None:
return None
return Section(*[y for x in value.strip("[]").split(",")
for start, end in [x.split(":")]
for y in (None if start == '' else int(start)-1,
Expand Down
21 changes: 15 additions & 6 deletions gemini_instruments/gemini/adclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import math
import datetime
import dateutil.parser
from itertools import chain

import numpy as np

Expand Down Expand Up @@ -384,17 +385,23 @@ def _dec(self):

def _parse_section(self, keyword, pretty):
try:
value_filter = (str if pretty else Section.from_string)
value_filter = lambda x: (x.asIRAFsection() if pretty else x)
process_fn = lambda x: (None if x is None else value_filter(x))
# Dummy keyword FULLFRAME returns shape of full data array
if keyword == 'FULLFRAME':
def _encode_shape(shape):
if not shape:
return None
return Section(*chain.from_iterable([(0, npix) for npix in shape[::-1]]))
if self.is_single:
sections = '[1:{1},1:{0}]'.format(*self.shape)
sections = _encode_shape(self.shape)
else:
sections = ['[1:{1},1:{0}]'.format(*ext.shape)
for ext in self]
sections = [_encode_shape(ext.shape) for ext in self]
else:
sections = self.hdr.get(keyword)
if self.is_single:
sections = Section.from_string(self.hdr.get(keyword))
else:
sections = [Section.from_string(sec) if sec is not None else None for sec in self.hdr.get(keyword)]
if self.is_single:
return process_fn(sections)
else:
Expand Down Expand Up @@ -2151,9 +2158,11 @@ def empirical_pixel_scale(ext):

pixel_scale_list = []
for ext in self:
if len(ext.shape) < 2:
return None
try:
pixel_scale_list.append(3600 * np.sqrt(abs(np.linalg.det(ext.wcs.forward_transform['cd_matrix'].matrix))))
except (IndexError, AttributeError):
except (IndexError, AttributeError) as iae:
scale = empirical_pixel_scale(ext)
if scale is not None:
pixel_scale_list.append(scale)
Expand Down
5 changes: 4 additions & 1 deletion geminidr/core/primitives_spect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2284,8 +2284,11 @@ def findApertures(self, adinputs=None, **params):
placeholders={"section": "e.g. 100:900,1500:2000"})

# pass "direction" purely for logging purposes
filename = ad.filename
if not filename:
filename = ad.orig_filename
locations, all_limits = interactive_find_source_apertures(
ext_oriented, ui_params=ui_params, **aper_params,
ext_oriented, ui_params=ui_params, filename=filename, **aper_params,
direction="column" if dispaxis == 0 else "row")
else:
locations, all_limits, _, _ = tracing.find_apertures(
Expand Down
2 changes: 1 addition & 1 deletion geminidr/core/primitives_visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ def plotSpectraForQA(self, adinputs=None, **params):
stack_size = 1

group_id = ad.group_id().split('_[')[0]
group_id += ad.group_id().split(']')[1]
group_id += ad.group_id().split(']')[-1]

offset = (ad.telescope_y_offset() if ad.dispersion_axis()[0] == 1
else ad.telescope_x_offset())
Expand Down
6 changes: 5 additions & 1 deletion geminidr/f2/recipes/qa/recipes_LS_SPECT.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
Recipes available to data with tags ['F2', 'SPECT', LS'].
Default is "reduceScience".
"""
from time import sleep

recipe_tags = {'F2', 'SPECT', 'LS'}


def reduceScience(p):
"""
To be updated as development continues: This recipe processes F2 longslit
Expand All @@ -20,6 +23,7 @@ def reduceScience(p):
p.ADUToElectrons()
p.addVAR(poisson_noise=True, read_noise=True)
p.darkCorrect()
p.measureIQ(display=True)
p.flatCorrect()
p.attachWavelengthSolution()
p.addToList(purpose='forSky')
Expand Down Expand Up @@ -48,7 +52,7 @@ def reduceScience(p):
p.measureIQ(display=True)
p.traceApertures()
p.extractSpectra()
p.plotspectraForQA()
p.plotSpectraForQA()


_default = reduceScience
3 changes: 3 additions & 0 deletions geminidr/gnirs/recipes/qa/recipes_LS_SPECT.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
recipe_tags = {'GNIRS', 'SPECT', 'LS'}


def reduceScience(p):
"""
To be updated as development continues: This recipe processes GNIRS longslit
Expand All @@ -19,6 +20,7 @@ def reduceScience(p):
# p.nonlinearityCorrect() # non-linearity correction tbd
p.ADUToElectrons()
p.addVAR(poisson_noise=True, read_noise=True)
p.measureIQ(display=True)
p.flatCorrect()
p.attachWavelengthSolution()
p.addToList(purpose='forSky')
Expand All @@ -37,6 +39,7 @@ def reduceScience(p):
# The GUI polls for new data every 3 seconds. The next steps can be
# quicker than that leading to the second plotSpectra to hijack this one.
# Hijacking issues were highlighted in integration tests.
from time import sleep
sleep(3)

# continuing with the main stream of 2D pre-stack
Expand Down
8 changes: 6 additions & 2 deletions geminidr/interactive/fit/aperture.py
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ def result(self):
return np.array(locations), limits


def interactive_find_source_apertures(ext, ui_params=None, **kwargs):
def interactive_find_source_apertures(ext, ui_params=None, filename=None, **kwargs):
"""
Perform an interactive find of source apertures with the given initial
parameters.
Expand All @@ -1012,6 +1012,10 @@ def interactive_find_source_apertures(ext, ui_params=None, **kwargs):
"""
model = FindSourceAperturesModel(ext, **kwargs)
fsav = FindSourceAperturesVisualizer(model, ui_params=ui_params, filename_info=ext.filename)
if not filename:
filename = ext.filename
if not filename and hasattr(ext, "orig_filename"):
filename = ext.orig_filename
fsav = FindSourceAperturesVisualizer(model, ui_params=ui_params, filename_info=filename)
interactive_fitter(fsav)
return fsav.result()
4 changes: 4 additions & 0 deletions geminidr/interactive/fit/fit1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def __init__(self, fitting_parameters, domain, x=None, y=None, weights=None,

self.fitting_parameters = fitting_parameters
self.domain = domain
self.fit = initial_fit
if len(x) == 0:
self.fit = initial_fit
self.listeners = listeners
Expand Down Expand Up @@ -390,6 +391,9 @@ def perform_fit(self, *args):
if rank >= fitparms["order"]:
self.quality = FitQuality.GOOD
self.fit = new_fit
elif self.fit is None:
self.quality = FitQuality.BAD
self.fit = new_fit
else:
# Modify the fit_1D object with a shift by ugly hacking
offset = np.mean(self.y[goodpix] - self.evaluate(self.x[goodpix]))
Expand Down
4 changes: 3 additions & 1 deletion geminidr/interactive/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,12 +634,14 @@ def _cb_handler(cbkey, val):
title = params.titles[key]
else:
title = _title_from_field(field)
val = self.ui_params.values.get(key, "")
widget = TextInput(title=title,
min_width=100,
max_width=256,
width_policy="fit",
placeholder=params.placeholders[key]
if key in params.placeholders else None)
if key in params.placeholders else None,
value=val)

class TextHandler:
def __init__(self, key, extras, fn):
Expand Down
2 changes: 1 addition & 1 deletion gempy/gemini/gemini_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ def fit_continuum(ad):
# are a multiple of 512 pixels. We do this because the data are
# unlikely to have gone through traceApertures() so we can't
# account for curvature in the spectral trace.
hwidth = 512 // spectral_bin
hwidth = min(512 // spectral_bin, dispersed_length // 2)
centers = [i*hwidth for i in range(1, dispersed_length // hwidth, 1)]
spectral_slices = [slice(center-hwidth, center+hwidth) for center in centers]

Expand Down
3 changes: 2 additions & 1 deletion gempy/library/fitsverify.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def fitsverify(filename):
subproc = subprocess.Popen([FITSVERIFY_BIN, filename], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(stdoutstring, stderrstring) = subproc.communicate()

stdoutstring += stderrstring

# Check to see if we got a not a fits file situation
nfmatch = NFRE.search(stdoutstring.decode('utf-8'))
if nfmatch:
Expand Down

0 comments on commit 077a330

Please sign in to comment.