Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow fwhm_fromlines for tilts calibration #1861

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pypeit/calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1176,11 +1176,14 @@ def get_tilts(self):
_spat_flexure = self.mstilt.spat_flexure \
if self.par['tiltframe']['process']['spat_flexure_correct'] else None

# get measured fwhm from wv_calib
measured_fwhms = [wvfit.fwhm for wvfit in self.wv_calib.wv_fits]

# Build
buildwaveTilts = wavetilts.BuildWaveTilts(
self.mstilt, self.slits, self.spectrograph, self.par['tilts'],
self.par['wavelengths'], det=self.det, qa_path=self.qa_path,
spat_flexure=_spat_flexure)
spat_flexure=_spat_flexure, measured_fwhms=measured_fwhms)

# TODO still need to deal with syntax for LRIS ghosts. Maybe we don't need it
self.wavetilts = buildwaveTilts.run(doqa=self.write_qa, show=self.show)
Expand Down
7 changes: 4 additions & 3 deletions pypeit/par/pypeitpar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2978,15 +2978,16 @@ def __init__(self, reference=None, method=None, echelle=None, ech_nspec_coeff=No
defaults['fwhm'] = 4.
dtypes['fwhm'] = [int, float]
descr['fwhm'] = 'Spectral sampling of the arc lines. This is the FWHM of an arcline in ' \
'binned pixels of the input arc image'
'binned pixels of the input arc image. Note that this is used also in the ' \
'wave tilts calibration.'

defaults['fwhm_fromlines'] = True
dtypes['fwhm_fromlines'] = bool
descr['fwhm_fromlines'] = 'Estimate spectral resolution in each slit using the arc lines. '\
'If True, the estimated FWHM will override ``fwhm`` only in '\
'If True, the estimated FWHM will override ``fwhm`` in '\
'the determination of the wavelength solution (including the ' \
'calculation of the threshold for the solution RMS, see ' \
'``rms_thresh_frac_fwhm``), but not for the wave tilts calibration.' \
'``rms_thresh_frac_fwhm``), and ALSO for the wave tilts calibration.' \

defaults['fwhm_spat_order'] = 0
dtypes['fwhm_spat_order'] = int
Expand Down
8 changes: 6 additions & 2 deletions pypeit/scripts/chk_tilts.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@

@staticmethod
def main(args):
from pathlib import Path

Check warning on line 35 in pypeit/scripts/chk_tilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/scripts/chk_tilts.py#L35

Added line #L35 was not covered by tests
from pypeit import wavetilts

chk_version = not args.try_old

# tilts file path
file = Path(args.file).absolute()

Check warning on line 41 in pypeit/scripts/chk_tilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/scripts/chk_tilts.py#L41

Added line #L41 was not covered by tests

# Load
tilts = wavetilts.WaveTilts.from_file(args.file, chk_version=chk_version)
tilts = wavetilts.WaveTilts.from_file(file, chk_version=chk_version)

Check warning on line 44 in pypeit/scripts/chk_tilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/scripts/chk_tilts.py#L44

Added line #L44 was not covered by tests
tilts.show(in_ginga=np.logical_not(args.mpl), show_traces=args.show_traces,
chk_version=chk_version)
calib_dir=file.parent, chk_version=chk_version)



84 changes: 59 additions & 25 deletions pypeit/wavetilts.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pypeit.display import display
from pypeit.core import arc
from pypeit.core import tracewave
from pypeit.core.wavecal import autoid
from pypeit.images import buildimage


Expand Down Expand Up @@ -174,7 +175,7 @@
return np.where(mtch)[0][0]

def show(self, waveimg=None, wcs_match=True, in_ginga=True, show_traces=False,
chk_version=True):
calib_dir=None, chk_version=True):
"""
Show in ginga or mpl Tiltimg with the tilts traced and fitted overlaid

Expand All @@ -188,22 +189,32 @@
If True, show the image in ginga. Otherwise, use matplotlib.
show_traces (bool, optional):
If True, show the traces of the tilts on the image.
calib_dir (`Path`_):
Path to the calibration directory. If None, the path is taken from the
WaveTilts object.
chk_version (:obj:`bool`, optional):
When reading in existing files written by PypeIt, perform strict
version checking to ensure a valid file. If False, the code
will try to keep going, but this may lead to faults and quiet
failures. User beware!
"""
# get tilt_img_dict
cal_file = Path(self.calib_dir).absolute() / self.tiltimg_filename
_calib_dir = self.calib_dir
if calib_dir is not None and calib_dir.exists():
_calib_dir = calib_dir
msgs.info(f'Searching for other calibration files in {str(_calib_dir)}')

Check warning on line 205 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L202-L205

Added lines #L202 - L205 were not covered by tests
else:
msgs.info(f'Searching for other calibration files in the default directory {str(_calib_dir)}')

Check warning on line 207 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L207

Added line #L207 was not covered by tests

cal_file = Path(_calib_dir).absolute() / self.tiltimg_filename

Check warning on line 209 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L209

Added line #L209 was not covered by tests
if cal_file.exists():
tilt_img_dict = buildimage.TiltImage.from_file(cal_file, chk_version=chk_version)
else:
msgs.error(f'Tilt image {str(cal_file)} NOT FOUND.')

# get slits
slitmask = None
cal_file = Path(self.calib_dir).absolute() / self.slits_filename
cal_file = Path(_calib_dir).absolute() / self.slits_filename

Check warning on line 217 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L217

Added line #L217 was not covered by tests
if cal_file.exists():
slits = slittrace.SlitTraceSet.from_file(cal_file, chk_version=chk_version)
_slitmask = slits.slit_img(initial=True, flexure=self.spat_flexure)
Expand All @@ -220,7 +231,7 @@
# get waveimg
same_size = (slits.nspec, slits.nspat) == tilt_img_dict.image.shape
if waveimg is None and slits is not None and same_size and in_ginga:
wv_calib_name = wavecalib.WaveCalib.construct_file_name(self.calib_key, calib_dir=self.calib_dir)
wv_calib_name = wavecalib.WaveCalib.construct_file_name(self.calib_key, calib_dir=_calib_dir)

Check warning on line 234 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L234

Added line #L234 was not covered by tests
if Path(wv_calib_name).absolute().exists():
wv_calib = wavecalib.WaveCalib.from_file(wv_calib_name, chk_version=chk_version)
tilts = self.fit2tiltimg(slitmask, flexure=self.spat_flexure)
Expand Down Expand Up @@ -268,24 +279,32 @@
slits (:class:`~pypeit.slittrace.SlitTraceSet`):
Slit edges
spectrograph (:class:`~pypeit.spectrographs.spectrograph.Spectrograph`):
Spectrograph object
The `Spectrograph` instance that sets the instrument used. Used to set
:attr:`spectrograph`.
par (:class:`~pypeit.par.pypeitpar.WaveTiltsPar` or None):
The parameters used to fuss with the tilts
The parameters used for the tilt calibration.
Uses ``['calibrations']['tilts']``.
wavepar (:class:`~pypeit.par.pypeitpar.WavelengthSolutionPar` or None):
The parameters used for the wavelength solution
det (int): Detector index
The parameters used for the wavelength solution.
Uses ``['calibrations']['wavelengths']``.
det (int):
Detector index
qa_path (:obj:`str`, optional):
Directory for QA output.
spat_flexure (float, optional):
If input, the slitmask and slit edges are shifted prior
to tilt analysis.
measured_fwhms (`numpy.ndarray`_, optional):
FWHM of the arc lines measured during wavecalib. If provided, this
will be used for arc/sky line detection.



Attributes:
spectrograph (:class:`~pypeit.spectrographs.spectrograph.Spectrograph`):
??
The `Spectrograph` instance that sets the instrument used.
steps (list):
??
List of the processing steps performed
mask (`numpy.ndarray`_):
boolean array; True = Ignore this slit
all_trcdict (list):
Expand All @@ -304,7 +323,7 @@

# TODO This needs to be modified to take an inmask
def __init__(self, mstilt, slits, spectrograph, par, wavepar, det=1, qa_path=None,
spat_flexure=None):
spat_flexure=None, measured_fwhms=None):

# TODO: Perform type checking
self.spectrograph = spectrograph
Expand All @@ -316,6 +335,7 @@
self.det = det
self.qa_path = qa_path
self.spat_flexure = spat_flexure
self.measured_fwhms = measured_fwhms if measured_fwhms is not None else np.array([None] * slits.nslits)

# Get the non-linear count level
if self.mstilt.is_mosaic:
Expand Down Expand Up @@ -385,23 +405,26 @@

return arccen, arccen_bpm

def find_lines(self, arcspec, slit_cen, slit_idx, bpm=None, debug=False):
def find_lines(self, arcspec, slit_cen, slit_idx, fwhm, bpm=None, debug=False):
"""
Find the lines for tracing

Wrapper to tracewave.tilts_find_lines()

Args:
arcspec ():
??
slit_cen ():
??
arcspec (`numpy.ndarray`_):
1D spectrum to be searched for significant detections.
slit_cen (`numpy.ndarray`_):
Trace down the center of the slit. Must match the shape of arcspec.
slit_idx (int):
Slit index, zero-based
Slit index, zero-based.
fwhm (float):
FWHM of the arc lines.
bpm (`numpy.ndarray`_, optional):
??
Bad-pixel mask for input spectrum. If None, all pixels considered good.
If passed, must match the shape of arcspec.
debug (bool, optional):
??
Show a QA plot for the line detection.

Returns:
tuple: 2 objectcs
Expand All @@ -423,7 +446,7 @@
sig_neigh=self.par['sig_neigh'],
nfwhm_neigh=self.par['nfwhm_neigh'],
only_these_lines=only_these_lines,
fwhm=self.wavepar['fwhm'],
fwhm=fwhm,
nonlinear_counts=self.nonlinear_counts,
bpm=bpm, debug_peaks=False, debug_lines=debug)

Expand Down Expand Up @@ -478,7 +501,7 @@
self.steps.append(inspect.stack()[0][3])
return self.all_fit_dict[slit_idx]['coeff2']

def trace_tilts(self, arcimg, lines_spec, lines_spat, thismask, slit_cen,
def trace_tilts(self, arcimg, lines_spec, lines_spat, thismask, slit_cen, fwhm,
debug_pca=False, show_tracefits=False):
"""
Trace the tilts
Expand All @@ -500,14 +523,20 @@
is (nspec, nspat) with dtype=bool.
slit_cen (:obj:`int`):
Integer index indicating the slit in question.
fwhm (:obj:`float`):
FWHM of the arc lines.
debug_pca (:obj:`bool`, optional):
Show the PCA modeling QA plots.
show_tracefits (:obj:`bool`, optional):
Show the trace fits.

Returns:
dict: Dictionary containing information on the traced tilts required
to fit the filts.

"""
trace_dict = tracewave.trace_tilts(arcimg, lines_spec, lines_spat, thismask, slit_cen,
inmask=self.gpm, fwhm=self.wavepar['fwhm'],
inmask=self.gpm, fwhm=fwhm,
spat_order=self.par['spat_order'],
maxdev_tracefit=self.par['maxdev_tracefit'],
sigrej_trace=self.par['sigrej_trace'],
Expand Down Expand Up @@ -561,11 +590,13 @@
for i in range(nslits):
if self.tilt_bpm[i]:
continue
# get FWHM for this slit
fwhm = autoid.set_fwhm(self.wavepar, measured_fwhm=self.measured_fwhms[i])

Check warning on line 594 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L594

Added line #L594 was not covered by tests
# TODO: What to do with the following iter_continuum parameters?:
# sigthresh, sigrej, niter_cont, cont_samp, cont_frac_fwhm
arc_continuum[:,i], arc_fitmask[:,i] \
= arc.iter_continuum(self.arccen[:,i], gpm=np.invert(self.arccen_bpm[:,i]),
fwhm=self.wavepar['fwhm'])
fwhm=fwhm)
# TODO: Original version. Please leave it for now.
# arc_fitmask[:,i], coeff \
# = utils.robust_polyfit_djs(spec, self.arccen[:,i], self.par['cont_order'],
Expand Down Expand Up @@ -677,6 +708,7 @@
# Subtract arc continuum
_mstilt = self.mstilt.image.copy()
if self.par['rm_continuum']:
msgs.info('Subtracting the continuum')

Check warning on line 711 in pypeit/wavetilts.py

View check run for this annotation

Codecov / codecov/patch

pypeit/wavetilts.py#L711

Added line #L711 was not covered by tests
continuum = self.model_arc_continuum(debug=debug)
_mstilt -= continuum
if debug:
Expand Down Expand Up @@ -713,11 +745,13 @@
self.slits.mask[slit_idx] = self.slits.bitmask.turn_on(self.slits.mask[slit_idx], 'BADTILTCALIB')
continue
msgs.info(f'Computing tilts for slit/order {self.slits.slitord_id[slit_idx]} ({slit_idx+1}/{self.slits.nslits})')
# Get the arc FWHM for this slit
fwhm = autoid.set_fwhm(self.wavepar, measured_fwhm=self.measured_fwhms[slit_idx], verbose=True)
# Identify lines for tracing tilts
msgs.info('Finding lines for tilt analysis')
self.lines_spec, self.lines_spat \
= self.find_lines(self.arccen[:,slit_idx], self.slitcen[:,slit_idx],
slit_idx,
slit_idx, fwhm,
bpm=self.arccen_bpm[:,slit_idx], debug=debug)

if self.lines_spec is None:
Expand All @@ -733,7 +767,7 @@
# each line.
msgs.info('Trace the tilts')
self.trace_dict = self.trace_tilts(_mstilt, self.lines_spec, self.lines_spat,
thismask, self.slitcen[:, slit_idx])
thismask, self.slitcen[:, slit_idx], fwhm)
# IF there are < 2 usable arc lines for tilt tracing, PCA fit does not work and the reduction crushes
# TODO investigate why some slits have <2 usable arc lines
if np.sum(self.trace_dict['use_tilt']) < 2:
Expand Down
Loading