From e0542b81cd17754da9b85cddae3a079c55f59707 Mon Sep 17 00:00:00 2001 From: rcooke Date: Thu, 25 Jan 2024 17:26:43 +0000 Subject: [PATCH 01/35] start of AAT --- pypeit/spectrographs/aat_uhrf.py | 290 +++++++++++++++++++++++++++++++ pypeit/telescopes.py | 12 ++ 2 files changed, 302 insertions(+) create mode 100644 pypeit/spectrographs/aat_uhrf.py diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py new file mode 100644 index 0000000000..3ee5e57638 --- /dev/null +++ b/pypeit/spectrographs/aat_uhrf.py @@ -0,0 +1,290 @@ +""" +Module for Shane/Kast specific methods. + +.. include:: ../include/links.rst +""" +import os + +from IPython import embed + +import numpy as np + +from astropy.time import Time + +from pypeit import msgs +from pypeit import telescopes +from pypeit.core import framematch +from pypeit.spectrographs import spectrograph +from pypeit.images import detector_container +from pypeit import data + + + +class AATUHRFSpectrograph(spectrograph.Spectrograph): + """ + Child to handle AAT/UHRF specific code + """ + ndet = 1 + telescope = telescopes.AATTelescopePar() + url = 'https://aat.anu.edu.au/science/instruments/decomissioned/uhrf/overview' + ql_supported = False + name = 'aat_uhrf' + camera = 'UHRF' + supported = True + header_name = 'uhrf' + + def get_detector_par(self, det, hdu=None): + """ + Return metadata for the selected detector. + + Args: + det (:obj:`int`): + 1-indexed detector number. + hdu (`astropy.io.fits.HDUList`_, optional): + The open fits file with the raw image of interest. If not + provided, frame-dependent parameters are set to a default. + + Returns: + :class:`~pypeit.images.detector_container.DetectorContainer`: + Object with the detector metadata. + """ + # Detector 1 + detector_dict = dict( + binning='1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning'), + det=1, + dataext=0, + specaxis=1, + specflip=False, + spatflip=False, + platescale=0.43, + saturation=65535., + mincounts=-1e10, + nonlinear=0.76, + numamplifiers=2, + gain=np.asarray([1.2, 1.2]), + ronoise=np.asarray([3.7, 3.7]), + xgap=0., + ygap=0., + ysize=1., + darkcurr=0.0, # e-/pixel/hour + # These are rows, columns on the raw frame, 1-indexed + datasec=np.asarray(['[:, 1:1024]', '[:, 1025:2048]']), + oscansec=np.asarray(['[:, 2050:2080]', '[:, 2081:2111]']), + ) + return detector_container.DetectorContainer(**detector_dict) + + @classmethod + def default_pypeit_par(cls): + """ + Return the default parameters to use for this instrument. + + Returns: + :class:`~pypeit.par.pypeitpar.PypeItPar`: Parameters required by + all of PypeIt methods. + """ + par = super().default_pypeit_par() + + # Ignore PCA + par['calibrations']['slitedges']['sync_predict'] = 'nearest' + # Bound the detector with slit edges if no edges are found + par['calibrations']['slitedges']['bound_detector'] = True + + # Always correct for flexure, starting with default parameters + par['flexure']['spec_method'] = 'boxcar' + # Set the default exposure time ranges for the frame typing + par['calibrations']['biasframe']['exprng'] = [None, 0.001] + par['calibrations']['darkframe']['exprng'] = [999999, None] # No dark frames + par['calibrations']['pinholeframe']['exprng'] = [999999, None] # No pinhole frames + par['calibrations']['pixelflatframe']['exprng'] = [0, None] + par['calibrations']['traceframe']['exprng'] = [0, None] + par['calibrations']['arcframe']['exprng'] = [None, 61] + par['calibrations']['standardframe']['exprng'] = [1, 61] + # + par['scienceframe']['exprng'] = [61, None] + par['sensfunc']['IR']['telgridfile'] = 'TellPCA_3000_26000_R10000.fits' + return par + + def init_meta(self): + """ + Define how metadata are derived from the spectrograph files. + + That is, this associates the PypeIt-specific metadata keywords + with the instrument-specific header cards using :attr:`meta`. + """ + self.meta = {} + # Required (core) + self.meta['ra'] = dict(ext=0, card='RA') + self.meta['dec'] = dict(ext=0, card='DEC') + self.meta['target'] = dict(ext=0, card='OBJECT') + # dispname is arm specific (blue/red) + self.meta['decker'] = dict(ext=0, card='SLIT_N') + self.meta['binning'] = dict(ext=0, card=None, default='1,1') + self.meta['mjd'] = dict(ext=0, card=None, compound=True) + self.meta['exptime'] = dict(ext=0, card='EXPTIME') + self.meta['airmass'] = dict(ext=0, card='AIRMASS') + # Additional ones, generally for configuration determination or time + self.meta['dichroic'] = dict(ext=0, card='BSPLIT_N') + self.meta['instrument'] = dict(ext=0, card='VERSION') + lamp_names = [ '1', '2', '3', '4', '5', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'] + for kk,lamp_name in enumerate(lamp_names): + self.meta['lampstat{:02d}'.format(kk+1)] = dict(ext=0, card='LAMPSTA{0}'.format(lamp_name)) + + def compound_meta(self, headarr, meta_key): + """ + Methods to generate metadata requiring interpretation of the header + data, instead of simply reading the value of a header card. + + Args: + headarr (:obj:`list`): + List of `astropy.io.fits.Header`_ objects. + meta_key (:obj:`str`): + Metadata keyword to construct. + + Returns: + object: Metadata value read from the header(s). + """ + if meta_key == 'mjd': + time = headarr[0]['DATE'] + ttime = Time(time, format='isot') + return ttime.mjd + msgs.error("Not ready for this compound meta") + + def configuration_keys(self): + """ + Return the metadata keys that define a unique instrument + configuration. + + This list is used by :class:`~pypeit.metadata.PypeItMetaData` to + identify the unique configurations among the list of frames read + for a given reduction. + + Returns: + :obj:`list`: List of keywords of data pulled from file headers + and used to constuct the :class:`~pypeit.metadata.PypeItMetaData` + object. + """ + # decker is not included because arcs are often taken with a 0.5" slit + return ['dispname', 'dichroic' ] + + def check_frame_type(self, ftype, fitstbl, exprng=None): + """ + Check for frames of the provided type. + + Args: + ftype (:obj:`str`): + Type of frame to check. Must be a valid frame type; see + frame-type :ref:`frame_type_defs`. + fitstbl (`astropy.table.Table`_): + The table with the metadata for one or more frames to check. + exprng (:obj:`list`, optional): + Range in the allowed exposure time for a frame of type + ``ftype``. See + :func:`pypeit.core.framematch.check_frame_exptime`. + + Returns: + `numpy.ndarray`_: Boolean array with the flags selecting the + exposures in ``fitstbl`` that are ``ftype`` type frames. + """ + good_exp = framematch.check_frame_exptime(fitstbl['exptime'], exprng) + if ftype in ['science', 'standard']: + return good_exp & self.lamps(fitstbl, 'off') + if ftype == 'bias': + return good_exp # & (fitstbl['target'] == 'Bias') + if ftype in ['pixelflat', 'trace', 'illumflat']: + # Flats and trace frames are typed together + return good_exp & self.lamps(fitstbl, 'dome') # & (fitstbl['target'] == 'Dome Flat') + if ftype in ['pinhole', 'dark']: + # Don't type pinhole or dark frames + return np.zeros(len(fitstbl), dtype=bool) + if ftype in ['arc', 'tilt']: + return good_exp & self.lamps(fitstbl, 'arcs')# & (fitstbl['target'] == 'Arcs') + + msgs.warn('Cannot determine if frames are of type {0}.'.format(ftype)) + return np.zeros(len(fitstbl), dtype=bool) + + def lamps(self, fitstbl, status): + """ + Check the lamp status. + + Args: + fitstbl (`astropy.table.Table`_): + The table with the fits header meta data. + status (:obj:`str`): + The status to check. Can be ``'off'``, ``'arcs'``, or + ``'dome'``. + + Returns: + `numpy.ndarray`_: A boolean array selecting fits files that meet + the selected lamp status. + + Raises: + ValueError: + Raised if the status is not one of the valid options. + """ + if status == 'off': + # Check if all are off + return np.all(np.array([ (fitstbl[k] == 'off') | (fitstbl[k] == 'None') + for k in fitstbl.keys() if 'lampstat' in k]), axis=0) + if status == 'arcs': + # Check if any arc lamps are on + arc_lamp_stat = [ 'lampstat{0:02d}'.format(i) for i in range(6,17) ] + return np.any(np.array([ fitstbl[k] == 'on' for k in fitstbl.keys() + if k in arc_lamp_stat]), axis=0) + if status == 'dome': + # Check if any dome lamps are on + dome_lamp_stat = [ 'lampstat{0:02d}'.format(i) for i in range(1,6) ] + return np.any(np.array([ fitstbl[k] == 'on' for k in fitstbl.keys() + if k in dome_lamp_stat]), axis=0) + raise ValueError('No implementation for status = {0}'.format(status)) + + def config_specific_par(self, scifile, inp_par=None): + """ + Modify the PypeIt parameters to hard-wired values used for + specific instrument configurations. + + Args: + scifile (:obj:`str`): + File to use when determining the configuration and how + to adjust the input parameters. + inp_par (:class:`~pypeit.par.parset.ParSet`, optional): + Parameter set used for the full run of PypeIt. If None, + use :func:`default_pypeit_par`. + + Returns: + :class:`~pypeit.par.parset.ParSet`: The PypeIt parameter set + adjusted for configuration specific parameter values. + """ + par = super().config_specific_par(scifile, inp_par=inp_par) + # TODO: Should we allow the user to override these? + + if self.get_meta_value(scifile, 'dispname') == '600/4310': + par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_600.fits' + elif self.get_meta_value(scifile, 'dispname') == '452/3306': + par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_452.fits' + elif self.get_meta_value(scifile, 'dispname') == '830/3460': # NOT YET TESTED + par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_830.fits' + else: + msgs.error("NEED TO ADD YOUR GRISM HERE!") + # Return + return par + + def raw_header_cards(self): + """ + Return additional raw header cards to be propagated in + downstream output files for configuration identification. + + The list of raw data FITS keywords should be those used to populate + the :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.configuration_keys` + or are used in :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.config_specific_par` + for a particular spectrograph, if different from the name of the + PypeIt metadata keyword. + + This list is used by :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.subheader_for_spec` + to include additional FITS keywords in downstream output files. + + Returns: + :obj:`list`: List of keywords from the raw data files that should + be propagated in output files. + """ + return ['GRISM_N', 'BSPLIT_N'] diff --git a/pypeit/telescopes.py b/pypeit/telescopes.py index e8bc8c3d3a..32e9cbff80 100644 --- a/pypeit/telescopes.py +++ b/pypeit/telescopes.py @@ -10,6 +10,18 @@ #TODO: Remove 'Par' from class name? + +class AATTelescopePar(TelescopePar): + def __init__(self): + loc = EarthLocation.of_site('Siding Spring Observatory') + super(AATTelescopePar, self).__init__(name='AAT', + longitude=loc.lon.to(units.deg).value, + latitude=loc.lat.to(units.deg).value, + elevation=loc.height.to(units.m).value, + diameter=3.9, + eff_aperture=12.0) + + class GTCTelescopePar(TelescopePar): def __init__(self): loc = EarthLocation.of_site('Roque de los Muchachos') From 3ddc81b15707c963f0a5bfe5ff6601acb84aa4a1 Mon Sep 17 00:00:00 2001 From: rcooke Date: Thu, 25 Jan 2024 21:58:28 +0000 Subject: [PATCH 02/35] start of UHRF --- pypeit/par/pypeitpar.py | 2 +- pypeit/pypeitsetup.py | 5 ++ pypeit/spectrographs/__init__.py | 3 +- pypeit/spectrographs/aat_uhrf.py | 104 ++++++++----------------------- 4 files changed, 34 insertions(+), 80 deletions(-) diff --git a/pypeit/par/pypeitpar.py b/pypeit/par/pypeitpar.py index 8409519610..5b3143faf4 100644 --- a/pypeit/par/pypeitpar.py +++ b/pypeit/par/pypeitpar.py @@ -5130,7 +5130,7 @@ def valid_telescopes(): """ Return the valid telescopes. """ - return [ 'GEMINI-N','GEMINI-S', 'KECK', 'SHANE', 'WHT', 'APF', 'TNG', 'VLT', 'MAGELLAN', 'LBT', 'MMT', + return ['AAT', 'GEMINI-N','GEMINI-S', 'KECK', 'SHANE', 'WHT', 'APF', 'TNG', 'VLT', 'MAGELLAN', 'LBT', 'MMT', 'KPNO', 'NOT', 'P200', 'BOK', 'GTC', 'SOAR', 'NTT', 'LDT', 'JWST', 'HILTNER'] def validate(self): diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index 89ff8c0207..0b15085b9c 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -186,6 +186,11 @@ def from_file_root(cls, root, spectrograph, extension='.fits'): Returns: :class:`PypeitSetup`: The instance of the class. """ + from pypeit.spectrographs.util import load_spectrograph + spec = load_spectrograph(spectrograph) + allext = spec.allowed_extensions + embed() + # TODO :: Check all allowed extensions return cls.from_rawfiles(io.files_from_extension(root, extension=extension), spectrograph) @classmethod diff --git a/pypeit/spectrographs/__init__.py b/pypeit/spectrographs/__init__.py index 3377156931..06efedfb57 100644 --- a/pypeit/spectrographs/__init__.py +++ b/pypeit/spectrographs/__init__.py @@ -3,11 +3,12 @@ # The import of all the spectrograph modules here is what enables the dynamic # compiling of all the available spectrographs below -from pypeit.spectrographs import gtc_osiris +from pypeit.spectrographs import aat_uhrf from pypeit.spectrographs import bok_bc from pypeit.spectrographs import gemini_flamingos from pypeit.spectrographs import gemini_gmos from pypeit.spectrographs import gemini_gnirs +from pypeit.spectrographs import gtc_osiris from pypeit.spectrographs import keck_esi from pypeit.spectrographs import keck_deimos from pypeit.spectrographs import keck_hires diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 3ee5e57638..ec572d11e4 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -32,6 +32,7 @@ class AATUHRFSpectrograph(spectrograph.Spectrograph): camera = 'UHRF' supported = True header_name = 'uhrf' + allowed_extensions = ["FTS"] def get_detector_par(self, det, hdu=None): """ @@ -48,21 +49,25 @@ def get_detector_par(self, det, hdu=None): :class:`~pypeit.images.detector_container.DetectorContainer`: Object with the detector metadata. """ + # Binning is not recorded in the header, so we need to estimate it based on the image size + binspat = int(np.floor(hdu[0].header['NAXIS1']/1024)) + binspec = int(np.floor(hdu[0].header['NAXIS2']/1024)) + print(binspat, binspec) # Detector 1 detector_dict = dict( - binning='1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning'), + binning=f'{binspat},{binspec}', det=1, dataext=0, specaxis=1, specflip=False, spatflip=False, - platescale=0.43, + platescale=0.05, # Not sure about this value saturation=65535., mincounts=-1e10, nonlinear=0.76, - numamplifiers=2, - gain=np.asarray([1.2, 1.2]), - ronoise=np.asarray([3.7, 3.7]), + numamplifiers=1, + gain=np.asarray([1.0]), # Not sure about this value + ronoise=np.asarray([0.0]), # Determine the read noise from the overscan region xgap=0., ygap=0., ysize=1., @@ -113,22 +118,19 @@ def init_meta(self): """ self.meta = {} # Required (core) - self.meta['ra'] = dict(ext=0, card='RA') - self.meta['dec'] = dict(ext=0, card='DEC') + self.meta['ra'] = dict(ext=0, card='APPRA') + self.meta['dec'] = dict(ext=0, card='APPDEC') self.meta['target'] = dict(ext=0, card='OBJECT') # dispname is arm specific (blue/red) - self.meta['decker'] = dict(ext=0, card='SLIT_N') + self.meta['decker'] = dict(ext=0, card=None, required=False) + self.meta['dispname'] = dict(ext=0, card='WINDOW') self.meta['binning'] = dict(ext=0, card=None, default='1,1') self.meta['mjd'] = dict(ext=0, card=None, compound=True) - self.meta['exptime'] = dict(ext=0, card='EXPTIME') - self.meta['airmass'] = dict(ext=0, card='AIRMASS') + self.meta['exptime'] = dict(ext=0, card='TOTALEXP') + self.meta['airmass'] = dict(ext=0, card='AIRMASS', required=False) # Additional ones, generally for configuration determination or time - self.meta['dichroic'] = dict(ext=0, card='BSPLIT_N') - self.meta['instrument'] = dict(ext=0, card='VERSION') - lamp_names = [ '1', '2', '3', '4', '5', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'] - for kk,lamp_name in enumerate(lamp_names): - self.meta['lampstat{:02d}'.format(kk+1)] = dict(ext=0, card='LAMPSTA{0}'.format(lamp_name)) + # self.meta['dichroic'] = dict(ext=0, card='BSPLIT_N') + # self.meta['instrument'] = dict(ext=0, card='VERSION') def compound_meta(self, headarr, meta_key): """ @@ -145,8 +147,9 @@ def compound_meta(self, headarr, meta_key): object: Metadata value read from the header(s). """ if meta_key == 'mjd': - time = headarr[0]['DATE'] - ttime = Time(time, format='isot') + time = headarr[0]['UTSTART'] + date = headarr[0]['UTDATE'] + ttime = Time(f'{date}T{time}', format='isot') return ttime.mjd msgs.error("Not ready for this compound meta") @@ -165,7 +168,7 @@ def configuration_keys(self): object. """ # decker is not included because arcs are often taken with a 0.5" slit - return ['dispname', 'dichroic' ] + return ['dispname'] def check_frame_type(self, ftype, fitstbl, exprng=None): """ @@ -188,55 +191,20 @@ def check_frame_type(self, ftype, fitstbl, exprng=None): """ good_exp = framematch.check_frame_exptime(fitstbl['exptime'], exprng) if ftype in ['science', 'standard']: - return good_exp & self.lamps(fitstbl, 'off') + return good_exp if ftype == 'bias': - return good_exp # & (fitstbl['target'] == 'Bias') + return good_exp if ftype in ['pixelflat', 'trace', 'illumflat']: # Flats and trace frames are typed together - return good_exp & self.lamps(fitstbl, 'dome') # & (fitstbl['target'] == 'Dome Flat') + return good_exp if ftype in ['pinhole', 'dark']: # Don't type pinhole or dark frames return np.zeros(len(fitstbl), dtype=bool) if ftype in ['arc', 'tilt']: - return good_exp & self.lamps(fitstbl, 'arcs')# & (fitstbl['target'] == 'Arcs') + return good_exp msgs.warn('Cannot determine if frames are of type {0}.'.format(ftype)) return np.zeros(len(fitstbl), dtype=bool) - - def lamps(self, fitstbl, status): - """ - Check the lamp status. - - Args: - fitstbl (`astropy.table.Table`_): - The table with the fits header meta data. - status (:obj:`str`): - The status to check. Can be ``'off'``, ``'arcs'``, or - ``'dome'``. - - Returns: - `numpy.ndarray`_: A boolean array selecting fits files that meet - the selected lamp status. - - Raises: - ValueError: - Raised if the status is not one of the valid options. - """ - if status == 'off': - # Check if all are off - return np.all(np.array([ (fitstbl[k] == 'off') | (fitstbl[k] == 'None') - for k in fitstbl.keys() if 'lampstat' in k]), axis=0) - if status == 'arcs': - # Check if any arc lamps are on - arc_lamp_stat = [ 'lampstat{0:02d}'.format(i) for i in range(6,17) ] - return np.any(np.array([ fitstbl[k] == 'on' for k in fitstbl.keys() - if k in arc_lamp_stat]), axis=0) - if status == 'dome': - # Check if any dome lamps are on - dome_lamp_stat = [ 'lampstat{0:02d}'.format(i) for i in range(1,6) ] - return np.any(np.array([ fitstbl[k] == 'on' for k in fitstbl.keys() - if k in dome_lamp_stat]), axis=0) - raise ValueError('No implementation for status = {0}'.format(status)) def config_specific_par(self, scifile, inp_par=None): """ @@ -268,23 +236,3 @@ def config_specific_par(self, scifile, inp_par=None): msgs.error("NEED TO ADD YOUR GRISM HERE!") # Return return par - - def raw_header_cards(self): - """ - Return additional raw header cards to be propagated in - downstream output files for configuration identification. - - The list of raw data FITS keywords should be those used to populate - the :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.configuration_keys` - or are used in :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.config_specific_par` - for a particular spectrograph, if different from the name of the - PypeIt metadata keyword. - - This list is used by :meth:`~pypeit.spectrographs.spectrograph.Spectrograph.subheader_for_spec` - to include additional FITS keywords in downstream output files. - - Returns: - :obj:`list`: List of keywords from the raw data files that should - be propagated in output files. - """ - return ['GRISM_N', 'BSPLIT_N'] From a9d1f99da7af020a04a705e316b71a4983f894b5 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 26 Jan 2024 09:51:21 +0000 Subject: [PATCH 03/35] allow search for multiple extensions --- pypeit/pypeitsetup.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index 0b15085b9c..788c54f177 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -186,12 +186,18 @@ def from_file_root(cls, root, spectrograph, extension='.fits'): Returns: :class:`PypeitSetup`: The instance of the class. """ - from pypeit.spectrographs.util import load_spectrograph spec = load_spectrograph(spectrograph) - allext = spec.allowed_extensions - embed() - # TODO :: Check all allowed extensions - return cls.from_rawfiles(io.files_from_extension(root, extension=extension), spectrograph) + allext = [extension] + filelist = io.files_from_extension(root, extension=extension) + # Check all allowed extensions as well + if spec.allowed_extensions is not None: + for ext in spec.allowed_extensions: + if ext not in allext: + filelist += io.files_from_extension(root, extension=ext) + allext += [ext] + msgs.info("Found {0} files with extensions: {1}".format(len(filelist), ", ".join(allext))) + # Check for files + return cls.from_rawfiles(filelist, spectrograph) @classmethod def from_rawfiles(cls, data_files:list, spectrograph:str, frametype=None): From 62c9febe182c3c8ff0ea65dd8d995daa5eea6dd3 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 26 Jan 2024 09:52:00 +0000 Subject: [PATCH 04/35] unique filenames only --- pypeit/pypeitsetup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index 788c54f177..7cb396d007 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -195,6 +195,8 @@ def from_file_root(cls, root, spectrograph, extension='.fits'): if ext not in allext: filelist += io.files_from_extension(root, extension=ext) allext += [ext] + # Only keep unique files + filelist = list(set(filelist)) msgs.info("Found {0} files with extensions: {1}".format(len(filelist), ", ".join(allext))) # Check for files return cls.from_rawfiles(filelist, spectrograph) From 6ec9a0208c2e803fc82701c650471fb2ed15cff8 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 26 Jan 2024 09:52:08 +0000 Subject: [PATCH 05/35] meta adjusted --- pypeit/spectrographs/aat_uhrf.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index ec572d11e4..0e1c043d07 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -19,7 +19,6 @@ from pypeit import data - class AATUHRFSpectrograph(spectrograph.Spectrograph): """ Child to handle AAT/UHRF specific code @@ -32,7 +31,7 @@ class AATUHRFSpectrograph(spectrograph.Spectrograph): camera = 'UHRF' supported = True header_name = 'uhrf' - allowed_extensions = ["FTS"] + allowed_extensions = [".FTS"] def get_detector_par(self, det, hdu=None): """ @@ -49,13 +48,11 @@ def get_detector_par(self, det, hdu=None): :class:`~pypeit.images.detector_container.DetectorContainer`: Object with the detector metadata. """ - # Binning is not recorded in the header, so we need to estimate it based on the image size - binspat = int(np.floor(hdu[0].header['NAXIS1']/1024)) - binspec = int(np.floor(hdu[0].header['NAXIS2']/1024)) - print(binspat, binspec) + # Retrieve the binning + binning = self.compound_meta(self.get_headarr(hdu), "binning") # Detector 1 detector_dict = dict( - binning=f'{binspat},{binspec}', + binning=binning, det=1, dataext=0, specaxis=1, @@ -122,9 +119,9 @@ def init_meta(self): self.meta['dec'] = dict(ext=0, card='APPDEC') self.meta['target'] = dict(ext=0, card='OBJECT') # dispname is arm specific (blue/red) - self.meta['decker'] = dict(ext=0, card=None, required=False) + self.meta['decker'] = dict(ext=0, card='WINDOW') self.meta['dispname'] = dict(ext=0, card='WINDOW') - self.meta['binning'] = dict(ext=0, card=None, default='1,1') + self.meta['binning'] = dict(ext=0, card=None, compound=True) self.meta['mjd'] = dict(ext=0, card=None, compound=True) self.meta['exptime'] = dict(ext=0, card='TOTALEXP') self.meta['airmass'] = dict(ext=0, card='AIRMASS', required=False) @@ -147,10 +144,14 @@ def compound_meta(self, headarr, meta_key): object: Metadata value read from the header(s). """ if meta_key == 'mjd': + date = headarr[0]['UTDATE'].replace(":","-") time = headarr[0]['UTSTART'] - date = headarr[0]['UTDATE'] ttime = Time(f'{date}T{time}', format='isot') return ttime.mjd + elif meta_key == 'binning': + binspat = int(np.ceil(1024/headarr[0]['NAXIS1'])) + binspec = int(np.ceil(1024/headarr[0]['NAXIS2'])) + return f'{binspat},{binspec}' msgs.error("Not ready for this compound meta") def configuration_keys(self): From 5ea5866d05c0d261fb73342f2dd8d24f0bbdeb55 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 26 Jan 2024 17:49:01 +0000 Subject: [PATCH 06/35] wavelength calibration --- .../reid_arxiv/aat_uhrf_UFC27405.fits | Bin 0 -> 23040 bytes pypeit/spectrographs/aat_uhrf.py | 55 +++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits diff --git a/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits b/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits new file mode 100644 index 0000000000000000000000000000000000000000..c82c34012c16a73218412b69fa056bd081a8a791 GIT binary patch literal 23040 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 T?FqDhe*PJOe@5W{wGsGVWg76Q literal 0 HcmV?d00001 diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 0e1c043d07..2a9e8d3c2d 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -50,12 +50,13 @@ def get_detector_par(self, det, hdu=None): """ # Retrieve the binning binning = self.compound_meta(self.get_headarr(hdu), "binning") + dsec = 1 + 1024//int(binning.split(',')[0]) # Detector 1 detector_dict = dict( binning=binning, det=1, dataext=0, - specaxis=1, + specaxis=0, specflip=False, spatflip=False, platescale=0.05, # Not sure about this value @@ -70,8 +71,8 @@ def get_detector_par(self, det, hdu=None): ysize=1., darkcurr=0.0, # e-/pixel/hour # These are rows, columns on the raw frame, 1-indexed - datasec=np.asarray(['[:, 1:1024]', '[:, 1025:2048]']), - oscansec=np.asarray(['[:, 2050:2080]', '[:, 2081:2111]']), + datasec=np.asarray(['[:, 1:{:d}]'.format(dsec)]), + oscansec=np.asarray(['[:, {:d}:]'.format(dsec+1)]) ) return detector_container.DetectorContainer(**detector_dict) @@ -91,19 +92,16 @@ def default_pypeit_par(cls): # Bound the detector with slit edges if no edges are found par['calibrations']['slitedges']['bound_detector'] = True - # Always correct for flexure, starting with default parameters - par['flexure']['spec_method'] = 'boxcar' + # Never correct for flexure + par['flexure']['spec_method'] = 'skip' + + # Set some parameters for the calibrations + par['calibrations']['wavelengths']['lamps'] = ['ThAr'] + # Set the default exposure time ranges for the frame typing - par['calibrations']['biasframe']['exprng'] = [None, 0.001] - par['calibrations']['darkframe']['exprng'] = [999999, None] # No dark frames - par['calibrations']['pinholeframe']['exprng'] = [999999, None] # No pinhole frames - par['calibrations']['pixelflatframe']['exprng'] = [0, None] - par['calibrations']['traceframe']['exprng'] = [0, None] - par['calibrations']['arcframe']['exprng'] = [None, 61] - par['calibrations']['standardframe']['exprng'] = [1, 61] - # + par['calibrations']['arcframe']['exprng'] = [None, 60.0] + par['calibrations']['tiltframe']['exprng'] = [None, 60.0] par['scienceframe']['exprng'] = [61, None] - par['sensfunc']['IR']['telgridfile'] = 'TellPCA_3000_26000_R10000.fits' return par def init_meta(self): @@ -124,7 +122,7 @@ def init_meta(self): self.meta['binning'] = dict(ext=0, card=None, compound=True) self.meta['mjd'] = dict(ext=0, card=None, compound=True) self.meta['exptime'] = dict(ext=0, card='TOTALEXP') - self.meta['airmass'] = dict(ext=0, card='AIRMASS', required=False) + self.meta['airmass'] = dict(ext=0, card=None, compound=True) # Additional ones, generally for configuration determination or time # self.meta['dichroic'] = dict(ext=0, card='BSPLIT_N') # self.meta['instrument'] = dict(ext=0, card='VERSION') @@ -152,6 +150,11 @@ def compound_meta(self, headarr, meta_key): binspat = int(np.ceil(1024/headarr[0]['NAXIS1'])) binspec = int(np.ceil(1024/headarr[0]['NAXIS2'])) return f'{binspat},{binspec}' + elif meta_key == 'airmass': + # Calculate the zenith distance + zendist = 0.5*(headarr[0]['ZDSTART']+headarr[0]['ZDEND']) + # Return the airmass based on the zenith distance + return 1./np.cos(np.deg2rad(zendist)) msgs.error("Not ready for this compound meta") def configuration_keys(self): @@ -191,13 +194,15 @@ def check_frame_type(self, ftype, fitstbl, exprng=None): exposures in ``fitstbl`` that are ``ftype`` type frames. """ good_exp = framematch.check_frame_exptime(fitstbl['exptime'], exprng) - if ftype in ['science', 'standard']: + if ftype in ['science']: return good_exp + if ftype in ['standard']: + return np.zeros(len(fitstbl), dtype=bool) if ftype == 'bias': - return good_exp + return np.zeros(len(fitstbl), dtype=bool) if ftype in ['pixelflat', 'trace', 'illumflat']: # Flats and trace frames are typed together - return good_exp + return np.zeros(len(fitstbl), dtype=bool) if ftype in ['pinhole', 'dark']: # Don't type pinhole or dark frames return np.zeros(len(fitstbl), dtype=bool) @@ -225,15 +230,11 @@ def config_specific_par(self, scifile, inp_par=None): adjusted for configuration specific parameter values. """ par = super().config_specific_par(scifile, inp_par=inp_par) - # TODO: Should we allow the user to override these? - - if self.get_meta_value(scifile, 'dispname') == '600/4310': - par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_600.fits' - elif self.get_meta_value(scifile, 'dispname') == '452/3306': - par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_452.fits' - elif self.get_meta_value(scifile, 'dispname') == '830/3460': # NOT YET TESTED - par['calibrations']['wavelengths']['reid_arxiv'] = 'shane_kast_blue_830.fits' + + if self.get_meta_value(scifile, 'dispname') == 'UHRF_X8': + par['calibrations']['wavelengths']['reid_arxiv'] = 'aat_uhrf_UFC27405.fits' + par['calibrations']['wavelengths']['method'] = 'full_template' else: - msgs.error("NEED TO ADD YOUR GRISM HERE!") + msgs.error("Wavelength setup not supported!") # Return return par From 23b8d5061074364c80140cdbbb46e8bb85935c44 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 26 Jan 2024 21:28:56 +0000 Subject: [PATCH 07/35] better wavelength solution --- pypeit/spectrographs/aat_uhrf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 2a9e8d3c2d..2e886436b7 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -97,6 +97,7 @@ def default_pypeit_par(cls): # Set some parameters for the calibrations par['calibrations']['wavelengths']['lamps'] = ['ThAr'] + par['calibrations']['wavelengths']['n_final'] = 3 # Set the default exposure time ranges for the frame typing par['calibrations']['arcframe']['exprng'] = [None, 60.0] From 367c6d4b4eeb789faec77567866b2bd52f9950bb Mon Sep 17 00:00:00 2001 From: rcooke Date: Sat, 27 Jan 2024 15:13:31 +0000 Subject: [PATCH 08/35] minor doc updates --- pypeit/spectrographs/aat_uhrf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 2e886436b7..0a31d2a67c 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -92,7 +92,7 @@ def default_pypeit_par(cls): # Bound the detector with slit edges if no edges are found par['calibrations']['slitedges']['bound_detector'] = True - # Never correct for flexure + # Never correct for flexure - the sky is subdominant compared to the object and basically never detected. par['flexure']['spec_method'] = 'skip' # Set some parameters for the calibrations @@ -100,8 +100,14 @@ def default_pypeit_par(cls): par['calibrations']['wavelengths']['n_final'] = 3 # Set the default exposure time ranges for the frame typing + # Trace frames should be the same as arc frames - it will force a bound detector and this + # allows the scattered light to be subtracted. A pixel-to-pixel sensitivity correction is + # not needed for this instrument, since it's a small slicer that projects the target onto + # multiple pixels. This instrument observes bright objects only, so sky subtraction is not + # important, but the sky subtraction routine is used to subtract scattered light, instead. par['calibrations']['arcframe']['exprng'] = [None, 60.0] par['calibrations']['tiltframe']['exprng'] = [None, 60.0] + par['calibrations']['traceframe']['exprng'] = [None, 60.0] par['scienceframe']['exprng'] = [61, None] return par From 13a8ccaa981023e774a767f700f557cc31f3b46d Mon Sep 17 00:00:00 2001 From: rcooke Date: Sat, 27 Jan 2024 15:34:10 +0000 Subject: [PATCH 09/35] parameter updates --- pypeit/spectrographs/aat_uhrf.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 0a31d2a67c..ab679a7805 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -95,6 +95,13 @@ def default_pypeit_par(cls): # Never correct for flexure - the sky is subdominant compared to the object and basically never detected. par['flexure']['spec_method'] = 'skip' + # Sky subtraction parameters - this instrument has no sky lines, but we still use the sky subtraction + # routine to subtract scattered light. + par['reduce']['skysub']['no_poly'] = False + par['reduce']['skysub']['bspline_spacing'] = 3.0 + par['reduce']['skysub']['user_regions'] = ':10,75:' # This is about right for most setups tested so far + par['scienceframe']['process']['sigclip'] = 100.0 + # Set some parameters for the calibrations par['calibrations']['wavelengths']['lamps'] = ['ThAr'] par['calibrations']['wavelengths']['n_final'] = 3 @@ -109,6 +116,7 @@ def default_pypeit_par(cls): par['calibrations']['tiltframe']['exprng'] = [None, 60.0] par['calibrations']['traceframe']['exprng'] = [None, 60.0] par['scienceframe']['exprng'] = [61, None] + return par def init_meta(self): From be3aafc0ea53cab965587ba9aa4a6da779428680 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 29 Jan 2024 09:32:16 +0000 Subject: [PATCH 10/35] CR update --- pypeit/spectrographs/aat_uhrf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index ab679a7805..ee953a4a59 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -100,7 +100,7 @@ def default_pypeit_par(cls): par['reduce']['skysub']['no_poly'] = False par['reduce']['skysub']['bspline_spacing'] = 3.0 par['reduce']['skysub']['user_regions'] = ':10,75:' # This is about right for most setups tested so far - par['scienceframe']['process']['sigclip'] = 100.0 + par['scienceframe']['process']['sigclip'] = 10.0 # Set some parameters for the calibrations par['calibrations']['wavelengths']['lamps'] = ['ThAr'] From 3f2698aefa762eea9721249ab2d190878538ac45 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 29 Jan 2024 09:32:39 +0000 Subject: [PATCH 11/35] improved object finding for short slits --- pypeit/core/arc.py | 57 +++++++++++++++++++++++++++++++++- pypeit/core/findobj_skymask.py | 11 +++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/pypeit/core/arc.py b/pypeit/core/arc.py index 45b9745907..07d1f82eaf 100644 --- a/pypeit/core/arc.py +++ b/pypeit/core/arc.py @@ -506,6 +506,7 @@ def get_censpec(slit_cen, slitmask, arcimg, gpm=None, box_rad=3.0, arc_spec[arc_spec_bpm] = 0.0 return arc_spec, arc_spec_bpm, np.all(arc_spec_bpm, axis=0) + def detect_peaks(x, mph=None, mpd=1, threshold=0, edge='rising', kpsh=False, valley=False, show=False, ax=None): """Detect peaks in data based on their amplitude and other features. @@ -782,7 +783,7 @@ def iter_continuum(spec, gpm=None, fwhm=4.0, sigthresh = 2.0, sigrej=3.0, niter_ max_nmask = int(np.ceil((max_mask_frac)*nspec_available)) for iter in range(niter_cont): spec_sub = spec - cont_now - mask_sigclip = np.invert(cont_mask & gpm) + mask_sigclip = np.logical_not(cont_mask & gpm) (mean, med, stddev) = stats.sigma_clipped_stats(spec_sub, mask=mask_sigclip, sigma_lower=sigrej, sigma_upper=sigrej, cenfunc='median', stdfunc=utils.nan_mad_std) # be very liberal in determining threshold for continuum determination @@ -1064,6 +1065,60 @@ def detect_lines(censpec, sigdetect=5.0, fwhm=4.0, fit_frac_fwhm=1.25, input_thr return tampl_true, tampl, tcent, twid, centerr, ww, arc, nsig +def mask_around_peaks(spec, inbpm): + """ + Find peaks in the input spectrum and mask pixels around them. + + All pixels to the left and right of a peak is masked until + a pixel has a lower value than the adjacent pixel. At this + point, we assume that spec has reached the noise level. + + Parameters + ---------- + spec: `numpy.ndarray`_ + Spectrum (1D array) in counts + inbpm: `numpy.ndarray`_ + Input bad pixel mask + + Returns + ------- + outbpm: `numpy.ndarray`_ + Bad pixel mask with pixels around peaks masked + """ + # Find the peak locations + pks = detect_peaks(spec) + + # Initialise some useful variables and the output bpm + xarray = np.arange(spec.size) + specdiff = np.append(np.diff(spec), 0.0) + outbpm = inbpm.copy() + + # Loop over the peaks and mask pixels around them + for i in range(len(pks)): + # Find all pixels to the left of the peak that are above the noise level + wl = np.where((xarray <= pks[i]) & (specdiff > 0.0))[0] + ww = (pks[i]-wl)[::-1] + # Find the first pixel to the left of the peak that is below the noise level + nmask = np.where(np.diff(ww) > 1)[0] + if nmask.size != 0 and nmask[0] > 5: + # Mask all pixels to the left of the peak + mini = max(0,wl.size-nmask[0]-1) + outbpm[wl[mini]:pks[i]] = True + # Find all pixels to the right of the peak that are above the noise level + ww = np.where((xarray >= pks[i]) & (specdiff < 0.0))[0] + # Find the first pixel to the right of the peak that is below the noise level + nmask = np.where(np.diff(ww) > 1)[0] + if nmask.size != 0 and nmask[0] > 5: + # Mask all pixels to the right of the peak + maxi = min(nmask[0], ww.size) + outbpm[pks[i]:ww[maxi]+2] = True + plt.plot(spec, 'k-', drawstyle='steps-mid') + plt.plot(np.logical_not(outbpm) * spec, 'r-', drawstyle='steps-mid') + plt.show() + # Return the output bpm + return outbpm + + def fit_arcspec(xarray, yarray, pixt, fitp): """ Fit a series of pre-identified arc spectrum lines. diff --git a/pypeit/core/findobj_skymask.py b/pypeit/core/findobj_skymask.py index dec86cb999..586bf8d0cd 100644 --- a/pypeit/core/findobj_skymask.py +++ b/pypeit/core/findobj_skymask.py @@ -2411,9 +2411,16 @@ def objs_in_slit(image, ivar, thismask, slit_left, slit_righ, gpm_smash = npix_smash > 0.3*nsmash flux_sum_smash = np.sum((image_rect*gpm_sigclip)[find_min_max_out[0]:find_min_max_out[1]], axis=0) flux_smash = flux_sum_smash*gpm_smash/(npix_smash + (npix_smash == 0.0)) + # Mask around the peaks + peak_bpm = arc.mask_around_peaks(flux_smash, np.logical_not(gpm_smash)) + # Check that the peak mask is not empty + if np.sum(np.logical_not(peak_bpm))/peak_bpm.size < 0.05: # 95% masked! + msgs.warn('Peak masking was too aggressive. Attempting to sigma clip.') + smash_mask = np.logical_not(gpm_smash) + else: + smash_mask = np.logical_not(gpm_smash) | peak_bpm flux_smash_mean, flux_smash_med, flux_smash_std = astropy.stats.sigma_clipped_stats( - flux_smash, mask=np.logical_not(gpm_smash), sigma_lower=3.0, sigma_upper=3.0 - ) + flux_smash, mask=smash_mask, sigma_lower=3.0, sigma_upper=3.0) flux_smash_recen = flux_smash - flux_smash_med # Return if none found and no hand extraction From c48753c580d446ec651da9209aa6228468ebf84c Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 29 Jan 2024 09:34:28 +0000 Subject: [PATCH 12/35] rm debug --- pypeit/core/arc.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pypeit/core/arc.py b/pypeit/core/arc.py index 07d1f82eaf..46588b35e3 100644 --- a/pypeit/core/arc.py +++ b/pypeit/core/arc.py @@ -1112,9 +1112,6 @@ def mask_around_peaks(spec, inbpm): # Mask all pixels to the right of the peak maxi = min(nmask[0], ww.size) outbpm[pks[i]:ww[maxi]+2] = True - plt.plot(spec, 'k-', drawstyle='steps-mid') - plt.plot(np.logical_not(outbpm) * spec, 'r-', drawstyle='steps-mid') - plt.show() # Return the output bpm return outbpm From d0b20193d57af7e8e0f70620f868499150b3108d Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 29 Jan 2024 16:15:51 +0000 Subject: [PATCH 13/35] logical not --- pypeit/core/skysub.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pypeit/core/skysub.py b/pypeit/core/skysub.py index b486282c73..030422540b 100644 --- a/pypeit/core/skysub.py +++ b/pypeit/core/skysub.py @@ -245,7 +245,6 @@ def global_skysub(image, ivar, tilts, thismask, slit_left, slit_righ, inmask=Non return ythis - def skyoptimal(piximg, data, ivar, oprof, sigrej=3.0, npoly=1, spatial_img=None, fullbkpt=None): """ Utility routine used by local_skysub_extract that performs the joint b-spline fit for sky-background @@ -898,7 +897,7 @@ def local_skysub_extract(sciimg, sciivar, tilts, waveimg, global_sky, thismask, isub, = np.where(localmask.flatten()) #sortpix = (piximg.flat[isub]).argsort() obj_profiles_flat = obj_profiles.reshape(nspec * nspat, objwork) - skymask = outmask & np.invert(edgmask) + skymask = outmask & np.logical_not(edgmask) sky_bmodel, obj_bmodel, outmask_opt = skyoptimal( piximg.flat[isub], sciimg.flat[isub], (modelivar * skymask).flat[isub], obj_profiles_flat[isub, :], spatial_img=spatial_img.flat[isub], From 13fc3945b8bdc1188d583e56f726f70b8c5c4fe4 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 29 Jan 2024 16:19:24 +0000 Subject: [PATCH 14/35] improved tilts --- pypeit/spectrographs/aat_uhrf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index ee953a4a59..1edd32e484 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -97,7 +97,7 @@ def default_pypeit_par(cls): # Sky subtraction parameters - this instrument has no sky lines, but we still use the sky subtraction # routine to subtract scattered light. - par['reduce']['skysub']['no_poly'] = False + par['reduce']['skysub']['no_poly'] = True par['reduce']['skysub']['bspline_spacing'] = 3.0 par['reduce']['skysub']['user_regions'] = ':10,75:' # This is about right for most setups tested so far par['scienceframe']['process']['sigclip'] = 10.0 @@ -105,6 +105,8 @@ def default_pypeit_par(cls): # Set some parameters for the calibrations par['calibrations']['wavelengths']['lamps'] = ['ThAr'] par['calibrations']['wavelengths']['n_final'] = 3 + par['calibrations']['tilts']['spat_order'] = 4 + par['calibrations']['tilts']['spec_order'] = 1 # Set the default exposure time ranges for the frame typing # Trace frames should be the same as arc frames - it will force a bound detector and this From e37a6c9cc58e94a6b34c73e24a90a0be4c60560d Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 26 Feb 2024 13:43:49 +0000 Subject: [PATCH 15/35] AAT/UHRF support --- doc/releases/1.15.1dev.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/releases/1.15.1dev.rst b/doc/releases/1.15.1dev.rst index 74c4826326..9dba67ea8a 100644 --- a/doc/releases/1.15.1dev.rst +++ b/doc/releases/1.15.1dev.rst @@ -15,6 +15,7 @@ Instrument-specific Updates --------------------------- - Added example of improved wavelength solution for GEMINI/GMOS +- Added support for the (decommissioned) AAT/UHRF instrument Script Changes -------------- From ed7001cf693e6a7389c8691539082676f25b0566 Mon Sep 17 00:00:00 2001 From: rcooke Date: Wed, 17 Jul 2024 16:30:12 +0100 Subject: [PATCH 16/35] update changes --- doc/releases/1.15.1dev.rst | 0 doc/releases/1.16.1dev.rst | 1 + 2 files changed, 1 insertion(+) delete mode 100644 doc/releases/1.15.1dev.rst diff --git a/doc/releases/1.15.1dev.rst b/doc/releases/1.15.1dev.rst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index fe68fc7496..dc2c778494 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -20,6 +20,7 @@ Functionality/Performance Improvements and Additions Instrument-specific Updates --------------------------- +- Added support for the (decommissioned) AAT/UHRF instrument Script Changes -------------- From c9029e6f0397d69e4b87904c9de80cb4868066df Mon Sep 17 00:00:00 2001 From: rcooke-ast Date: Wed, 31 Jul 2024 16:10:57 +0100 Subject: [PATCH 17/35] add AAT/UHRF --- pypeit/spectrographs/aat_uhrf.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 1edd32e484..52d0a00d67 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -103,6 +103,7 @@ def default_pypeit_par(cls): par['scienceframe']['process']['sigclip'] = 10.0 # Set some parameters for the calibrations + # par['calibrations']['wavelengths']['reid_arxiv'] = 'None' par['calibrations']['wavelengths']['lamps'] = ['ThAr'] par['calibrations']['wavelengths']['n_final'] = 3 par['calibrations']['tilts']['spat_order'] = 4 @@ -130,8 +131,8 @@ def init_meta(self): """ self.meta = {} # Required (core) - self.meta['ra'] = dict(ext=0, card='APPRA') - self.meta['dec'] = dict(ext=0, card='APPDEC') + self.meta['ra'] = dict(ext=0, card='MEANRA') + self.meta['dec'] = dict(ext=0, card='MEANDEC') self.meta['target'] = dict(ext=0, card='OBJECT') # dispname is arm specific (blue/red) self.meta['decker'] = dict(ext=0, card='WINDOW') @@ -248,10 +249,9 @@ def config_specific_par(self, scifile, inp_par=None): """ par = super().config_specific_par(scifile, inp_par=inp_par) - if self.get_meta_value(scifile, 'dispname') == 'UHRF_X8': - par['calibrations']['wavelengths']['reid_arxiv'] = 'aat_uhrf_UFC27405.fits' - par['calibrations']['wavelengths']['method'] = 'full_template' - else: - msgs.error("Wavelength setup not supported!") + if par['calibrations']['wavelengths']['reid_arxiv'] is None: + msgs.warn("Wavelength setup not supported!" + msgs.newline() + msgs.newline() + + "Please perform your own wavelength calibration, and provide the path+filename using:" + msgs.newline() + + msgs.pypeitpar_text(['calibrations', 'wavelengths', 'reid_arxiv = '])) # Return return par From 76af9f75e23b6cc14913599114964b2ffc8e93a5 Mon Sep 17 00:00:00 2001 From: rcooke-ast Date: Wed, 31 Jul 2024 16:18:06 +0100 Subject: [PATCH 18/35] add AAT/UHRF wavelength solution (CN) --- .../arc_lines/reid_arxiv/aat_uhrf_3875.fits | Bin 0 -> 23040 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pypeit/data/arc_lines/reid_arxiv/aat_uhrf_3875.fits diff --git a/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_3875.fits b/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_3875.fits new file mode 100644 index 0000000000000000000000000000000000000000..4e2009a9023ed2d109037a2addc4d4be1aa0a722 GIT binary patch literal 23040 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 Date: Wed, 31 Jul 2024 20:15:57 +0100 Subject: [PATCH 19/35] doc updates --- doc/spectrographs/aat_uhrf.rst | 33 +++++++++++++++++++++++++++++ doc/spectrographs/spectrographs.rst | 1 + 2 files changed, 34 insertions(+) create mode 100644 doc/spectrographs/aat_uhrf.rst diff --git a/doc/spectrographs/aat_uhrf.rst b/doc/spectrographs/aat_uhrf.rst new file mode 100644 index 0000000000..ebef209ecf --- /dev/null +++ b/doc/spectrographs/aat_uhrf.rst @@ -0,0 +1,33 @@ +.. highlight:: rest + +******** +AAT UHRF +******** + + +Overview +======== + +This file summarizes several instrument specific +settings that are related to AAT/UHRF. + + +Wavelength Calibration +---------------------- + +UHRF has many wavelength setups, and the wavelength calibration +must be performed manually for each setup using :ref:`wvcalib-byhand` +approach and the :ref:`pypeit_identify` script. Since this spectrograph +is decommissioned, we do not expect to have a general solution +for this spectrograph. + +Object profile +-------------- + +UHRF is a slicer spectrograph, and the data are usually binned aggressively. +The object profile tends to be poorly characterised with the automated approach, +and you may need to generate your own wavelength dependent profile. Previously, +a Gaussian KDE profile was used, and this performed well, but is not available +by default. For users that are interested in this functionality, please contact +the PypeIt developers on the PypeIt User's Slack, or see the `aat_uhrf_rjc` +branch. diff --git a/doc/spectrographs/spectrographs.rst b/doc/spectrographs/spectrographs.rst index 275915a2c9..1fffa34730 100644 --- a/doc/spectrographs/spectrographs.rst +++ b/doc/spectrographs/spectrographs.rst @@ -33,6 +33,7 @@ instrument-specific details for running PypeIt. :caption: Spectrographs :maxdepth: 1 + aat_uhrf gemini_flamingos2 gemini_gmos gemini_gnirs From f12276c05b65963cc54ba0ba79b5a47af9ee2394 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Fri, 2 Aug 2024 08:02:47 -0700 Subject: [PATCH 20/35] interrupt --- pypeit/inputfiles.py | 3 +- pypeit/io.py | 44 +++++++++++++++------------- pypeit/pypeitsetup.py | 2 -- pypeit/spectrographs/spectrograph.py | 2 +- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/pypeit/inputfiles.py b/pypeit/inputfiles.py index 952f40142b..52a41f7c11 100644 --- a/pypeit/inputfiles.py +++ b/pypeit/inputfiles.py @@ -1149,6 +1149,5 @@ def grab_rawfiles(file_of_files:str=None, list_of_files:list=None, raw_paths:lis return [str(p / f) for p in _raw_paths for f in list_of_files if (p / f).exists()] # Find all files that have the correct extension - return np.concatenate([files_from_extension(str(p), extension=extension) - for p in _raw_paths]).tolist() + return files_from_extension(_raw_paths, extension=extension) diff --git a/pypeit/io.py b/pypeit/io.py index 2e0c13b992..83b3710dec 100644 --- a/pypeit/io.py +++ b/pypeit/io.py @@ -851,40 +851,44 @@ def create_symlink(filename, symlink_dir, relative_symlink=False, overwrite=Fals os.symlink(olink_src, olink_dest) -def files_from_extension(raw_path, - extension:str='fits'): +def files_from_extension(raw_path, extension='.fits'): """ - Grab the list of files with a given extension + Find files from one or more paths with one or more extensions Args: - raw_path (str or list): - Path(s) to raw files, which may or may not include the prefix of the - files to search for. + raw_path (:obj:`str`, `Path`_, :obj:`list`): + One or more paths to search for files, which may or may not include + the prefix of the files to search for. - For a string input, for example, this can be the directory - ``'/path/to/files/'`` or the directory plus the file prefix - ``'/path/to/files/prefix'``, which yeilds the search strings - ``'/path/to/files/*fits'`` or ``'/path/to/files/prefix*fits'``, - respectively. + For string input, this can be the directory ``'/path/to/files/'`` or + the directory plus the file prefix ``'/path/to/files/prefix'``, + which yeilds the search strings ``'/path/to/files/*fits'`` or + ``'/path/to/files/prefix*fits'``, respectively. For a list input, this can use wildcards for multiple directories. - extension (str, optional): - File extension to search on. + extension (str, list, optional): + One or more file extensions to search on. Returns: list: List of raw data filenames (sorted) with full path """ - if isinstance(raw_path, str): - # Grab the list of files - dfname = os.path.join(raw_path, f'*{extension}*') \ - if os.path.isdir(raw_path) else f'{raw_path}*{extension}*' - return sorted(glob.glob(dfname)) + if isinstance(raw_path, (str, Path)): + _raw_path = Path(raw_path).absolute() + if _raw_path.is_dir(): + prefix = '' + else: + _raw_path, prefix = _raw_path.parent, _raw_path.name + if not _raw_path.is_dir(): + msgs.error(f'{_raw_path} does not exist!') + ext = extension if isinstance(extension, list) else [extension] + return numpy.concatenate([sorted(_raw_path.glob(f'{prefix}*{e}*')) for e in ext]).tolist() if isinstance(raw_path, list): - return numpy.concatenate([files_from_extension(p, extension=extension) for p in raw_path]).tolist() + return numpy.concatenate([files_from_extension(p, extension=extension) + for p in raw_path]).tolist() - msgs.error(f"Incorrect type {type(raw_path)} for raw_path (must be str or list)") + msgs.error(f"Incorrect type {type(raw_path)} for raw_path; must be str, Path, or list.") diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index badfd1e6d4..3d168075f7 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -163,8 +163,6 @@ def from_pypeit_file(cls, filename): cfg_lines=pypeItFile.cfg_lines, pypeit_file=filename) - # TODO: Make the default here match the default used by - # io.files_from_extension? @classmethod def from_file_root(cls, root, spectrograph, extension='.fits'): """ diff --git a/pypeit/spectrographs/spectrograph.py b/pypeit/spectrographs/spectrograph.py index 4c8de5d4a9..bb1619d555 100644 --- a/pypeit/spectrographs/spectrograph.py +++ b/pypeit/spectrographs/spectrograph.py @@ -145,7 +145,7 @@ class Spectrograph: Metadata model that is generic to all spectrographs. """ - allowed_extensions = None + allowed_extensions = ['.fits', '.fits.gz'] """ Defines the allowed extensions for the input fits files. """ From 15db2c32912e8306376bfb93851fd3ee0bf19478 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Fri, 2 Aug 2024 09:02:56 -0700 Subject: [PATCH 21/35] before testing --- pypeit/io.py | 34 ++++++++++++++----------- pypeit/pypeitsetup.py | 37 ++++++++++++--------------- pypeit/spectrographs/spectrograph.py | 38 ++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/pypeit/io.py b/pypeit/io.py index 83b3710dec..cacfaf9164 100644 --- a/pypeit/io.py +++ b/pypeit/io.py @@ -853,25 +853,28 @@ def create_symlink(filename, symlink_dir, relative_symlink=False, overwrite=Fals def files_from_extension(raw_path, extension='.fits'): """ - Find files from one or more paths with one or more extensions + Find files from one or more paths with one or more extensions. + + This is a recursive function. If ``raw_path`` is a list, the function is + called for every item in the list and the results are concatenated. Args: raw_path (:obj:`str`, `Path`_, :obj:`list`): One or more paths to search for files, which may or may not include - the prefix of the files to search for. - - For string input, this can be the directory ``'/path/to/files/'`` or - the directory plus the file prefix ``'/path/to/files/prefix'``, - which yeilds the search strings ``'/path/to/files/*fits'`` or - ``'/path/to/files/prefix*fits'``, respectively. - - For a list input, this can use wildcards for multiple directories. - - extension (str, list, optional): + the prefix of the files to search for. For string input, this can + be the directory ``'/path/to/files/'`` or the directory plus the + file prefix ``'/path/to/files/prefix'``, which yeilds the search + strings ``'/path/to/files/*fits'`` or + ``'/path/to/files/prefix*fits'``, respectively. For a list input, + this can use wildcards for multiple directories. + + extension (:obj:`str`, :obj:`list`, optional): One or more file extensions to search on. Returns: - list: List of raw data filenames (sorted) with full path + :obj:`list`: List of `Path`_ objects with the full path to the set of + unique raw data filenames that match the provided criteria search + strings. """ if isinstance(raw_path, (str, Path)): _raw_path = Path(raw_path).absolute() @@ -882,11 +885,12 @@ def files_from_extension(raw_path, extension='.fits'): if not _raw_path.is_dir(): msgs.error(f'{_raw_path} does not exist!') ext = extension if isinstance(extension, list) else [extension] - return numpy.concatenate([sorted(_raw_path.glob(f'{prefix}*{e}*')) for e in ext]).tolist() + files = numpy.concatenate([sorted(_raw_path.glob(f'{prefix}*{e}*')) for e in ext]) + return numpy.unique(files).tolist() if isinstance(raw_path, list): - return numpy.concatenate([files_from_extension(p, extension=extension) - for p in raw_path]).tolist() + files = numpy.concatenate([files_from_extension(p, extension=extension) for p in raw_path]) + return numpy.unique(files).tolist() msgs.error(f"Incorrect type {type(raw_path)} for raw_path; must be str, Path, or list.") diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index 3d168075f7..1ca991db7b 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -164,40 +164,35 @@ def from_pypeit_file(cls, filename): pypeit_file=filename) @classmethod - def from_file_root(cls, root, spectrograph, extension='.fits'): + def from_file_root(cls, root, spectrograph, extension=None): """ Instantiate the :class:`~pypeit.pypeitsetup.PypeItSetup` object by providing a file root. Args: - root (:obj:`str`): - String used to find the raw files; see + root (:obj:`str`, `Path`_, :obj:`list`): + One or more paths within which to search for files; see :func:`~pypeit.io.files_from_extension`. - spectrograph (:obj:`str`): + spectrograph (:obj:`str`, :class:`~pypeit.spectrographs.spectrograph.Spectrograph`): The PypeIt name of the spectrograph used to take the observations. This should be one of the available options in :attr:`~pypeit.spectrographs.available_spectrographs`. - extension (:obj:`str`, optional): + extension (:obj:`str`, :obj:`list`, optional): The extension common to all the fits files to reduce; see - :func:`~pypeit.io.files_from_extension`. - + :func:`~pypeit.io.files_from_extension`. If None, uses the + ``allowed_extensions`` of the spectrograph class. Otherwise, + this *must* be a subset of the allowed extensions for the + selected spectrograph. + Returns: :class:`PypeitSetup`: The instance of the class. """ - spec = load_spectrograph(spectrograph) - allext = [extension] - filelist = io.files_from_extension(root, extension=extension) - # Check all allowed extensions as well - if spec.allowed_extensions is not None: - for ext in spec.allowed_extensions: - if ext not in allext: - filelist += io.files_from_extension(root, extension=ext) - allext += [ext] - # Only keep unique files - filelist = list(set(filelist)) - msgs.info("Found {0} files with extensions: {1}".format(len(filelist), ", ".join(allext))) - # Check for files - return cls.from_rawfiles(filelist, spectrograph) + # NOTE: This works if `spectrograph` is either a string or a + # Spectrograph object + spec = load_spectrograph(spectrograph).__class__ + files = spec.find_raw_files(root, extension=extension) + msgs.info(f'Found {len(files)} {spec.name} raw files.') + return cls.from_rawfiles(files, spectrograph) @classmethod def from_rawfiles(cls, data_files:list, spectrograph:str, frametype=None): diff --git a/pypeit/spectrographs/spectrograph.py b/pypeit/spectrographs/spectrograph.py index bb1619d555..155efafbd1 100644 --- a/pypeit/spectrographs/spectrograph.py +++ b/pypeit/spectrographs/spectrograph.py @@ -269,6 +269,44 @@ def ql_par(): ) ) ) + + @classmethod + def find_raw_files(cls, root, extension=None): + """ + Find raw observations for this spectrograph in the provided directory. + + This is a wrapper for :func:`~pypeit.io.files_from_extension` that + handles the restrictions of the file extensions specific to this + spectrograph. + + Args: + root (:obj:`str`, `Path`_, :obj:`list`): + One or more paths to search for files, which may or may not include + the prefix of the files to search for. For string input, this can + be the directory ``'/path/to/files/'`` or the directory plus the + file prefix ``'/path/to/files/prefix'``, which yeilds the search + strings ``'/path/to/files/*fits'`` or + ``'/path/to/files/prefix*fits'``, respectively. For a list input, + this can use wildcards for multiple directories. + extension (:obj:`str`, :obj:`list`, optional): + One or more file extensions to search on. If None, uses + :attr:`allowed_extensions`. Otherwise, this *must* be a subset + of the allowed extensions for the selected spectrograph. + + Returns: + :obj:`list`: List of `Path`_ objects with the full path to the set of + unique raw data filenames that match the provided criteria search + strings. + """ + if extension is None: + _ext = cls.allowed_extensions + else: + _ext = extension if hasattr(extension, '__len__') else [extension] + _ext = [e for e in _ext if e in cls.allowed_extensions] + if len(_ext) == 0: + msgs.error(f'{extension} is not or does not include allowed extensions for ' + f'{cls.name}; choose from {cls.allowed_extensions}.') + return io.files_from_extension(root, extension=_ext) def _check_extensions(self, filename): """ From 76c5d305eb5003d84a43c8b94ecd9d2ed369b1a9 Mon Sep 17 00:00:00 2001 From: rcooke Date: Sat, 10 Aug 2024 14:25:25 +0100 Subject: [PATCH 22/35] flip check --- pypeit/spectrographs/keck_kcwi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pypeit/spectrographs/keck_kcwi.py b/pypeit/spectrographs/keck_kcwi.py index cdf4a20b10..abb0bd1179 100644 --- a/pypeit/spectrographs/keck_kcwi.py +++ b/pypeit/spectrographs/keck_kcwi.py @@ -860,7 +860,7 @@ def get_detector_par(self, det, hdu=None): # Some properties of the image binning = self.compound_meta(self.get_headarr(hdu), "binning") numamps = hdu[0].header['NVIDINP'] - specflip = True if hdu[0].header['AMPID1'] == 2 else False + specflip = False if hdu[0].header['AMPMODE'] == 'ALL' else True gainmul, gainarr = hdu[0].header['GAINMUL'], np.zeros(numamps) ronarr = np.zeros(numamps) # Set this to zero (determine the readout noise from the overscan regions) # dsecarr = np.array(['']*numamps) From 7f59d949a15d7a77d4ba2cf78cec0620d02ea519 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 12 Aug 2024 15:26:58 -0700 Subject: [PATCH 23/35] switch instance test --- pypeit/io.py | 4 ++-- pypeit/spectrographs/spectrograph.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pypeit/io.py b/pypeit/io.py index cacfaf9164..1d230ca5eb 100644 --- a/pypeit/io.py +++ b/pypeit/io.py @@ -884,8 +884,8 @@ def files_from_extension(raw_path, extension='.fits'): _raw_path, prefix = _raw_path.parent, _raw_path.name if not _raw_path.is_dir(): msgs.error(f'{_raw_path} does not exist!') - ext = extension if isinstance(extension, list) else [extension] - files = numpy.concatenate([sorted(_raw_path.glob(f'{prefix}*{e}*')) for e in ext]) + ext = [extension] if isinstance(extension, str) else extension + files = numpy.concatenate([sorted(_raw_path.glob(f'{prefix}*{e}')) for e in ext]) return numpy.unique(files).tolist() if isinstance(raw_path, list): diff --git a/pypeit/spectrographs/spectrograph.py b/pypeit/spectrographs/spectrograph.py index 155efafbd1..bc4aa24fa5 100644 --- a/pypeit/spectrographs/spectrograph.py +++ b/pypeit/spectrographs/spectrograph.py @@ -301,7 +301,7 @@ def find_raw_files(cls, root, extension=None): if extension is None: _ext = cls.allowed_extensions else: - _ext = extension if hasattr(extension, '__len__') else [extension] + _ext = [extension] if isinstance(extension, str) else extension _ext = [e for e in _ext if e in cls.allowed_extensions] if len(_ext) == 0: msgs.error(f'{extension} is not or does not include allowed extensions for ' From 23d471adc31528bcf49e71fd21983b8b5e1beb16 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 12 Aug 2024 16:41:24 -0700 Subject: [PATCH 24/35] fix file extensions --- pypeit/spectrographs/gemini_gnirs.py | 1 + pypeit/spectrographs/mdm_modspec.py | 2 ++ pypeit/spectrographs/wht_isis.py | 1 + 3 files changed, 4 insertions(+) diff --git a/pypeit/spectrographs/gemini_gnirs.py b/pypeit/spectrographs/gemini_gnirs.py index 5a88298847..989b58a677 100644 --- a/pypeit/spectrographs/gemini_gnirs.py +++ b/pypeit/spectrographs/gemini_gnirs.py @@ -587,6 +587,7 @@ class GNIRSIFUSpectrograph(GeminiGNIRSSpectrograph): # * Need to store a wavelength solution for different grating options (Note, the Holy Grail algorithm works pretty well, most of the time) name = 'gemini_gnirs_ifu' pypeline = 'SlicerIFU' + allowed_extensions = ['.fits', '.fits.bz2'] def init_meta(self): super().init_meta() diff --git a/pypeit/spectrographs/mdm_modspec.py b/pypeit/spectrographs/mdm_modspec.py index 68b1dbe2c6..25f0f78077 100644 --- a/pypeit/spectrographs/mdm_modspec.py +++ b/pypeit/spectrographs/mdm_modspec.py @@ -31,6 +31,8 @@ class MDMModspecEchelleSpectrograph(spectrograph.Spectrograph): supported = True comment = 'MDM Modspec spectrometer; Only 1200l/mm disperser (so far)' + allowed_extensions = ['.fit'] + def get_detector_par(self, det, hdu=None): """ Return metadata for the selected detector. diff --git a/pypeit/spectrographs/wht_isis.py b/pypeit/spectrographs/wht_isis.py index e107264ac3..38aab5006b 100644 --- a/pypeit/spectrographs/wht_isis.py +++ b/pypeit/spectrographs/wht_isis.py @@ -125,6 +125,7 @@ class WHTISISBlueSpectrograph(WHTISISSpectrograph): name = 'wht_isis_blue' camera = 'ISISb' comment = 'Blue camera' + allowed_extensions = ['.fit.gz'] def get_detector_par(self, det, hdu=None): """ From 75aa277d63b8ce70784c36098202a57975c79506 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Tue, 13 Aug 2024 09:01:58 -0700 Subject: [PATCH 25/35] test + doc fixes --- doc/api/pypeit.scripts.extract_datacube.rst | 8 + doc/api/pypeit.scripts.rst | 1 + doc/api/pypeit.spectrographs.aat_uhrf.rst | 8 + doc/api/pypeit.spectrographs.rst | 1 + doc/coadd3d.rst | 8 +- doc/help/pypeit_cache_github_data.rst | 2 +- doc/help/pypeit_chk_for_calibs.rst | 9 +- doc/help/pypeit_extract_datacube.rst | 29 ++ doc/help/pypeit_obslog.rst | 9 +- doc/help/pypeit_ql.rst | 2 +- doc/help/pypeit_sensfunc.rst | 12 +- doc/help/pypeit_setup.rst | 9 +- doc/help/pypeit_trace_edges.rst | 20 +- doc/help/pypeit_view_fits.rst | 2 +- doc/help/run_pypeit.rst | 10 +- doc/include/class_datamodel_pypeitimage.rst | 1 + doc/include/inst_detector_table.rst | 1 + doc/include/keck_deimos.sorted.rst | 10 +- doc/include/spectrographs_table.rst | 1 + doc/pypeit_par.rst | 310 +++++++++++++------- doc/releases/1.16.1dev.rst | 3 +- pypeit/core/datacube.py | 2 +- pypeit/flatfield.py | 29 +- pypeit/images/combineimage.py | 7 +- pypeit/scripts/chk_for_calibs.py | 7 +- pypeit/scripts/coadd_1dspec.py | 64 +--- pypeit/scripts/multislit_flexure.py | 49 ---- pypeit/scripts/obslog.py | 10 +- pypeit/scripts/setup.py | 7 +- pypeit/scripts/setup_gui.py | 7 +- pypeit/spectrographs/aat_uhrf.py | 2 +- pypeit/spectrographs/spectrograph.py | 4 +- pypeit/tests/test_calibrations.py | 10 +- pypeit/tests/test_io.py | 2 +- pypeit/tests/test_metadata.py | 2 +- pypeit/tests/test_setups.py | 4 +- 36 files changed, 360 insertions(+), 302 deletions(-) create mode 100644 doc/api/pypeit.scripts.extract_datacube.rst create mode 100644 doc/api/pypeit.spectrographs.aat_uhrf.rst create mode 100644 doc/help/pypeit_extract_datacube.rst diff --git a/doc/api/pypeit.scripts.extract_datacube.rst b/doc/api/pypeit.scripts.extract_datacube.rst new file mode 100644 index 0000000000..49f3a9d13e --- /dev/null +++ b/doc/api/pypeit.scripts.extract_datacube.rst @@ -0,0 +1,8 @@ +pypeit.scripts.extract\_datacube module +======================================= + +.. automodule:: pypeit.scripts.extract_datacube + :members: + :private-members: + :undoc-members: + :show-inheritance: diff --git a/doc/api/pypeit.scripts.rst b/doc/api/pypeit.scripts.rst index 38fbcf5584..9709614544 100644 --- a/doc/api/pypeit.scripts.rst +++ b/doc/api/pypeit.scripts.rst @@ -26,6 +26,7 @@ Submodules pypeit.scripts.compare_sky pypeit.scripts.compile_wvarxiv pypeit.scripts.edge_inspector + pypeit.scripts.extract_datacube pypeit.scripts.flux_calib pypeit.scripts.flux_setup pypeit.scripts.identify diff --git a/doc/api/pypeit.spectrographs.aat_uhrf.rst b/doc/api/pypeit.spectrographs.aat_uhrf.rst new file mode 100644 index 0000000000..2f4e657404 --- /dev/null +++ b/doc/api/pypeit.spectrographs.aat_uhrf.rst @@ -0,0 +1,8 @@ +pypeit.spectrographs.aat\_uhrf module +===================================== + +.. automodule:: pypeit.spectrographs.aat_uhrf + :members: + :private-members: + :undoc-members: + :show-inheritance: diff --git a/doc/api/pypeit.spectrographs.rst b/doc/api/pypeit.spectrographs.rst index c53968bcbb..239d591126 100644 --- a/doc/api/pypeit.spectrographs.rst +++ b/doc/api/pypeit.spectrographs.rst @@ -7,6 +7,7 @@ Submodules .. toctree:: :maxdepth: 4 + pypeit.spectrographs.aat_uhrf pypeit.spectrographs.bok_bc pypeit.spectrographs.gemini_flamingos pypeit.spectrographs.gemini_gmos diff --git a/doc/coadd3d.rst b/doc/coadd3d.rst index 5651dd0ee2..4e16390484 100644 --- a/doc/coadd3d.rst +++ b/doc/coadd3d.rst @@ -155,7 +155,7 @@ There are several recommended steps of the coadd3d process that can be run separ pypeit_sensfunc spec1d_StandardStarName.fits -o sens_StandardStarName.fits - For further details, see :doc:`_sensitivity_function`. + For further details, see :ref:`sensitivity_function`. #. Step 4 - Generate a datacube of the science exposures. This is done by running the following command: @@ -164,7 +164,7 @@ There are several recommended steps of the coadd3d process that can be run separ pypeit_coadd_datacube ScienceName.coadd3d -o Note that you will need to specify the sensitivity function file using the ``sensfile`` option in the - :doc:`coadd3d_file` file. For further details, see :ref:`coadd3d_fluxing`. + :ref:`coadd3d_file` file. For further details, see :ref:`coadd3d_fluxing`. Combination options =================== @@ -239,7 +239,7 @@ If you would like to flux calibrate your datacube, you need to produce your standard star datacube first. Then extract the spectrum of the standard star using the ``pypeit_extract_datacube`` script. This will produce a ``spec1d`` file that you will need to use to generate a -sensitivity function in the usual way (see :doc:`_sensitivity_function`). +sensitivity function in the usual way (see :ref:`sensitivity_function`). Then, when generating the datacube of the science frame you must include the name of the sensitivity function in your ``coadd3d`` file as follows: @@ -289,7 +289,7 @@ then you can specify the ``skysub_frame`` in the ``spec2d`` block of the above. If you have dedicated sky frames, then it is generally recommended to reduce these frames as if they are regular science frames, but add the following keyword arguments at the top of your -:doc:`coadd3d_file`: +:ref:`coadd3d_file`: .. code-block:: ini diff --git a/doc/help/pypeit_cache_github_data.rst b/doc/help/pypeit_cache_github_data.rst index 804e0656f2..0c3b6990b5 100644 --- a/doc/help/pypeit_cache_github_data.rst +++ b/doc/help/pypeit_cache_github_data.rst @@ -9,7 +9,7 @@ Script to download/cache PypeIt github data positional arguments: - spectrograph A valid spectrograph identifier: bok_bc, + spectrograph A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, diff --git a/doc/help/pypeit_chk_for_calibs.rst b/doc/help/pypeit_chk_for_calibs.rst index 06cc2d6357..653b5d1e81 100644 --- a/doc/help/pypeit_chk_for_calibs.rst +++ b/doc/help/pypeit_chk_for_calibs.rst @@ -13,7 +13,7 @@ options: -h, --help show this help message and exit -s SPECTROGRAPH, --spectrograph SPECTROGRAPH - A valid spectrograph identifier: bok_bc, + A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, @@ -35,8 +35,11 @@ vlt_xshooter_nir, vlt_xshooter_uvb, vlt_xshooter_vis, wht_isis_blue, wht_isis_red (default: None) -e EXTENSION, --extension EXTENSION - File extension; compression indicators (e.g. .gz) not - required. (default: .fits) + File extension to use. Must include the period (e.g., + ".fits") and it must be one of the allowed extensions + for this spectrograph. If None, root directory will be + searched for all files with any of the allowed + extensions. (default: None) --save_setups If not toggled, remove setup_files/ folder and its files. (default: False) \ No newline at end of file diff --git a/doc/help/pypeit_extract_datacube.rst b/doc/help/pypeit_extract_datacube.rst new file mode 100644 index 0000000000..f4b16eab69 --- /dev/null +++ b/doc/help/pypeit_extract_datacube.rst @@ -0,0 +1,29 @@ +.. code-block:: console + + $ pypeit_extract_datacube -h + usage: pypeit_extract_datacube [-h] [-e EXT_FILE] [-s SAVE] [-o] + [-b BOXCAR_RADIUS] [-v VERBOSITY] + file + + Read in a datacube, extract a spectrum of a point source,and save it as a spec1d + file. + + positional arguments: + file spec3d.fits DataCube file + + options: + -h, --help show this help message and exit + -e EXT_FILE, --ext_file EXT_FILE + Configuration file with extraction parameters (default: + None) + -s SAVE, --save SAVE Output spec1d filename (default: None) + -o, --overwrite Overwrite any existing files/directories (default: + False) + -b BOXCAR_RADIUS, --boxcar_radius BOXCAR_RADIUS + Radius of the circular boxcar (in arcseconds) to use for + the extraction. (default: None) + -v VERBOSITY, --verbosity VERBOSITY + Verbosity level between 0 [none] and 2 [all]. Default: + 1. Level 2 writes a log with filename + extract_datacube_YYYYMMDD-HHMM.log (default: 1) + \ No newline at end of file diff --git a/doc/help/pypeit_obslog.rst b/doc/help/pypeit_obslog.rst index 3b4c807e8c..5b399fcee0 100644 --- a/doc/help/pypeit_obslog.rst +++ b/doc/help/pypeit_obslog.rst @@ -10,7 +10,7 @@ using PypeItMetaData. positional arguments: - spec A valid spectrograph identifier: bok_bc, + spec A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, @@ -75,8 +75,11 @@ -s SORT, --sort SORT Metadata keyword (pypeit-specific) to use to sort the output table. (default: mjd) -e EXTENSION, --extension EXTENSION - File extension; compression indicators (e.g. .gz) not - required. (default: .fits) + File extension to use. Must include the period (e.g., + ".fits") and it must be one of the allowed extensions + for this spectrograph. If None, root directory will be + searched for all files with any of the allowed + extensions. (default: None) -d OUTPUT_PATH, --output_path OUTPUT_PATH Path to top-level output directory. (default: current working directory) diff --git a/doc/help/pypeit_ql.rst b/doc/help/pypeit_ql.rst index b8991c356d..9302bc39c0 100644 --- a/doc/help/pypeit_ql.rst +++ b/doc/help/pypeit_ql.rst @@ -17,7 +17,7 @@ Script to produce quick-look PypeIt reductions positional arguments: - spectrograph A valid spectrograph identifier: bok_bc, + spectrograph A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, diff --git a/doc/help/pypeit_sensfunc.rst b/doc/help/pypeit_sensfunc.rst index 3a5b008e28..8eb7d65e05 100644 --- a/doc/help/pypeit_sensfunc.rst +++ b/doc/help/pypeit_sensfunc.rst @@ -62,11 +62,13 @@ -s SENS_FILE, --sens_file SENS_FILE Configuration file with sensitivity function parameters -f FLATFILE, --flatfile FLATFILE - Use the flat file for computing the sensitivity - function. Note that it is not possible to set - --flatfile and simultaneously use a .sens file with the - --sens_file option. If you are using a .sens file, set - the flatfile there via e.g.: + Use a flat calibration file to compute the blaze + function when generating the sensitivity function. This + is helpful to account for small scale undulations in the + sensitivity function. Note that it is not possible to + set --flatfile and simultaneously use a .sens file with + the --sens_file option. If you are using a .sens file, + set the flatfile there via e.g.: [sensfunc] flatfile = Calibrations/Flat_A_0_DET01.fits diff --git a/doc/help/pypeit_setup.rst b/doc/help/pypeit_setup.rst index 32f4da9915..01e0c078dd 100644 --- a/doc/help/pypeit_setup.rst +++ b/doc/help/pypeit_setup.rst @@ -11,7 +11,7 @@ options: -h, --help show this help message and exit -s SPECTROGRAPH, --spectrograph SPECTROGRAPH - A valid spectrograph identifier: bok_bc, + A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, @@ -39,8 +39,11 @@ --extension option to set the types of files to search for. (default: current working directory) -e EXTENSION, --extension EXTENSION - File extension; compression indicators (e.g. .gz) not - required. (default: .fits) + File extension to use. Must include the period (e.g., + ".fits") and it must be one of the allowed extensions + for this spectrograph. If None, root directory will be + searched for all files with any of the allowed + extensions. (default: None) -d OUTPUT_PATH, --output_path OUTPUT_PATH Path to top-level output directory. (default: current working directory) diff --git a/doc/help/pypeit_trace_edges.rst b/doc/help/pypeit_trace_edges.rst index dc265db21b..a9b5e21814 100644 --- a/doc/help/pypeit_trace_edges.rst +++ b/doc/help/pypeit_trace_edges.rst @@ -26,16 +26,16 @@ default mosaic. (default: None) -s SPECTROGRAPH, --spectrograph SPECTROGRAPH A valid spectrograph identifier, which is only used if - providing files directly: bok_bc, gemini_flamingos1, - gemini_flamingos2, gemini_gmos_north_e2v, - gemini_gmos_north_ham, gemini_gmos_north_ham_ns, - gemini_gmos_south_ham, gemini_gnirs_echelle, - gemini_gnirs_ifu, gtc_maat, gtc_osiris, gtc_osiris_plus, - jwst_nircam, jwst_nirspec, keck_deimos, keck_esi, - keck_hires, keck_kcrm, keck_kcwi, keck_lris_blue, - keck_lris_blue_orig, keck_lris_red, keck_lris_red_mark4, - keck_lris_red_orig, keck_mosfire, keck_nires, - keck_nirspec_high, keck_nirspec_high_old, + providing files directly: aat_uhrf, bok_bc, + gemini_flamingos1, gemini_flamingos2, + gemini_gmos_north_e2v, gemini_gmos_north_ham, + gemini_gmos_north_ham_ns, gemini_gmos_south_ham, + gemini_gnirs_echelle, gemini_gnirs_ifu, gtc_maat, + gtc_osiris, gtc_osiris_plus, jwst_nircam, jwst_nirspec, + keck_deimos, keck_esi, keck_hires, keck_kcrm, keck_kcwi, + keck_lris_blue, keck_lris_blue_orig, keck_lris_red, + keck_lris_red_mark4, keck_lris_red_orig, keck_mosfire, + keck_nires, keck_nirspec_high, keck_nirspec_high_old, keck_nirspec_low, lbt_luci1, lbt_luci2, lbt_mods1b, lbt_mods1r, lbt_mods2b, lbt_mods2r, ldt_deveny, magellan_fire, magellan_fire_long, magellan_mage, diff --git a/doc/help/pypeit_view_fits.rst b/doc/help/pypeit_view_fits.rst index fb6bbd14e2..4ee223de61 100644 --- a/doc/help/pypeit_view_fits.rst +++ b/doc/help/pypeit_view_fits.rst @@ -9,7 +9,7 @@ View FITS files with ginga positional arguments: - spectrograph A valid spectrograph identifier: bok_bc, + spectrograph A valid spectrograph identifier: aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, gemini_gmos_north_ham, gemini_gmos_north_ham_ns, gemini_gmos_south_ham, diff --git a/doc/help/run_pypeit.rst b/doc/help/run_pypeit.rst index 2870d8a61a..62402415ec 100644 --- a/doc/help/run_pypeit.rst +++ b/doc/help/run_pypeit.rst @@ -7,11 +7,11 @@ ## PypeIt : The Python Spectroscopic Data Reduction Pipeline v1.16.1.dev109+g885cb1823 ## ## Available spectrographs include: - ## bok_bc, gemini_flamingos1, gemini_flamingos2, gemini_gmos_north_e2v, - ## gemini_gmos_north_ham, gemini_gmos_north_ham_ns, - ## gemini_gmos_south_ham, gemini_gnirs_echelle, gemini_gnirs_ifu, - ## gtc_maat, gtc_osiris, gtc_osiris_plus, jwst_nircam, jwst_nirspec, - ## keck_deimos, keck_esi, keck_hires, keck_kcrm, keck_kcwi, + ## aat_uhrf, bok_bc, gemini_flamingos1, gemini_flamingos2, + ## gemini_gmos_north_e2v, gemini_gmos_north_ham, + ## gemini_gmos_north_ham_ns, gemini_gmos_south_ham, gemini_gnirs_echelle, + ## gemini_gnirs_ifu, gtc_maat, gtc_osiris, gtc_osiris_plus, jwst_nircam, + ## jwst_nirspec, keck_deimos, keck_esi, keck_hires, keck_kcrm, keck_kcwi, ## keck_lris_blue, keck_lris_blue_orig, keck_lris_red, ## keck_lris_red_mark4, keck_lris_red_orig, keck_mosfire, keck_nires, ## keck_nirspec_high, keck_nirspec_high_old, keck_nirspec_low, lbt_luci1, diff --git a/doc/include/class_datamodel_pypeitimage.rst b/doc/include/class_datamodel_pypeitimage.rst index 1f21b5588b..9008ab7bc3 100644 --- a/doc/include/class_datamodel_pypeitimage.rst +++ b/doc/include/class_datamodel_pypeitimage.rst @@ -10,6 +10,7 @@ Attribute Type ``det_img`` `numpy.ndarray`_ `numpy.integer`_ If a detector mosaic, this image provides the detector that contributed to each pixel. ``detector`` :class:`~pypeit.images.detector_container.DetectorContainer`, :class:`~pypeit.images.mosaic.Mosaic` The detector (see :class:`~pypeit.images.detector_container.DetectorContainer`) or mosaic (see :class:`~pypeit.images.mosaic.Mosaic`) parameters ``exptime`` int, float Effective exposure time (s) +``filename`` str Filename for the image ``fullmask`` :class:`~pypeit.images.imagebitmask.ImageBitMaskArray` Image mask ``image`` `numpy.ndarray`_ `numpy.floating`_ Primary image data ``img_scale`` `numpy.ndarray`_ `numpy.floating`_ Image count scaling applied (e.g., 1/flat-field) diff --git a/doc/include/inst_detector_table.rst b/doc/include/inst_detector_table.rst index cbb0df365a..d30393c4f2 100644 --- a/doc/include/inst_detector_table.rst +++ b/doc/include/inst_detector_table.rst @@ -1,6 +1,7 @@ ============================ === ======== ======== ======== ======== ========================== ====================== ======== ======== ============ ========= ========== Instrument Det specaxis specflip spatflip namp gain RN darkcurr min sat nonlinear platescale ============================ === ======== ======== ======== ======== ========================== ====================== ======== ======== ============ ========= ========== +``aat_uhrf`` 1 0 False False 1 1.0 0.0 0.0 -1.0e+10 65535.0 0.7600 0.0500 ``bok_bc`` 1 1 False False 1 1.5 3.0 5.4 -1.0e+10 65535.0 1.0000 0.2000 ``gemini_flamingos1`` 1 0 False False 1 3.8 6.0 1080.0 -1.0e+10 320000.0 0.8750 0.1500 ``gemini_flamingos2`` 1 0 True False 1 4.44 5.0 1800.0 -1.0e+10 700000.0 1.0000 0.1787 diff --git a/doc/include/keck_deimos.sorted.rst b/doc/include/keck_deimos.sorted.rst index 4e41db2257..828519122f 100644 --- a/doc/include/keck_deimos.sorted.rst +++ b/doc/include/keck_deimos.sorted.rst @@ -12,17 +12,17 @@ filename | frametype | ra | dec | target | dispname | decker | binning | mjd | airmass | exptime | dispangle | amp | filter1 | lampstat01 | dateobs | utc | frameno | calib DE.20170527.06713.fits | arc,tilt | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.077631 | 1.41291034 | 1.0 | 8099.98291016 | SINGLE:B | OG550 | Kr Xe Ar Ne | 2017-05-27 | 01:51:53.87 | 30 | 0 d0527_0030.fits.gz | arc,tilt | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.077631 | 1.41291034 | 1.0 | 8099.98291016 | SINGLE:B | OG550 | Kr Xe Ar Ne | 2017-05-27 | 01:51:53.87 | 30 | 0 - DE.20170527.06790.fits | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.07851 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:53:10.93 | 31 | 0 d0527_0031.fits.gz | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.07851 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:53:10.93 | 31 | 0 - d0527_0032.fits.gz | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.079356 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:54:24.03 | 32 | 0 + DE.20170527.06790.fits | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.07851 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:53:10.93 | 31 | 0 DE.20170527.06864.fits | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.079356 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:54:24.03 | 32 | 0 - DE.20170527.06936.fits | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.080211 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:55:36.93 | 33 | 0 + d0527_0032.fits.gz | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.079356 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:54:24.03 | 32 | 0 d0527_0033.fits.gz | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.080211 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:55:36.93 | 33 | 0 + DE.20170527.06936.fits | pixelflat,illumflat,trace | 57.99999999999999 | 45.0 | DOME PHLAT | 830G | LongMirr | 1,1 | 57900.080211 | 1.41291034 | 4.0 | 8099.98291016 | SINGLE:B | OG550 | Qz | 2017-05-27 | 01:55:36.93 | 33 | 0 DE.20170527.37601.fits | science | 261.0363749999999 | 19.028166666666667 | P261_OFF | 830G | LongMirr | 1,1 | 57900.435131 | 1.03078874 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 10:26:41.61 | 80 | 0 - DE.20170527.38872.fits | science | 261.0363749999999 | 19.028166666666667 | P261_OFF | 830G | LongMirr | 1,1 | 57900.449842 | 1.01267696 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 10:47:52.92 | 81 | 0 d0527_0081.fits.gz | science | 261.0363749999999 | 19.028166666666667 | P261_OFF | 830G | LongMirr | 1,1 | 57900.449842 | 1.01267696 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 10:47:52.92 | 81 | 0 - d0527_0083.fits.gz | science | 261.0362916666666 | 19.028888888888886 | P261_OFF | 830G | LongMirr | 1,1 | 57900.483427 | 1.00093023 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 11:36:15.35 | 83 | 0 + DE.20170527.38872.fits | science | 261.0363749999999 | 19.028166666666667 | P261_OFF | 830G | LongMirr | 1,1 | 57900.449842 | 1.01267696 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 10:47:52.92 | 81 | 0 DE.20170527.41775.fits | science | 261.0362916666666 | 19.028888888888886 | P261_OFF | 830G | LongMirr | 1,1 | 57900.483427 | 1.00093023 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 11:36:15.35 | 83 | 0 + d0527_0083.fits.gz | science | 261.0362916666666 | 19.028888888888886 | P261_OFF | 830G | LongMirr | 1,1 | 57900.483427 | 1.00093023 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 11:36:15.35 | 83 | 0 DE.20170527.43045.fits | science | 261.0362916666666 | 19.028888888888886 | P261_OFF | 830G | LongMirr | 1,1 | 57900.498135 | 1.00838805 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 11:57:25.35 | 84 | 0 DE.20170527.44316.fits | science | 261.0362916666666 | 19.028888888888886 | P261_OFF | 830G | LongMirr | 1,1 | 57900.512854 | 1.02377681 | 1200.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 12:18:36.71 | 85 | 0 DE.20170527.53184.fits | science | 349.99316666666664 | -5.16575 | Feige 110 | 830G | LongMirr | 1,1 | 57900.615484 | 1.42505162 | 45.0 | 8099.98291016 | SINGLE:B | OG550 | Off | 2017-05-27 | 14:46:24.88 | 93 | 0 diff --git a/doc/include/spectrographs_table.rst b/doc/include/spectrographs_table.rst index 1244f6e8e8..5af65a3f2b 100644 --- a/doc/include/spectrographs_table.rst +++ b/doc/include/spectrographs_table.rst @@ -1,6 +1,7 @@ ======================== ============================================================================ ========= ============ =============================================================================================================================== ========= ========= ========= =============================================================================================== ``PypeIt`` Name ``PypeIt`` Class Telescope Camera URL Pipeline Supported QL Tested Comments ======================== ============================================================================ ========= ============ =============================================================================================================================== ========= ========= ========= =============================================================================================== +aat_uhrf :class:`~pypeit.spectrographs.aat_uhrf.AATUHRFSpectrograph` AAT UHRF `Link `__ MultiSlit True False bok_bc :class:`~pypeit.spectrographs.bok_bc.BokBCSpectrograph` BOK BC `Link `__ MultiSlit True False Bok B&C spectrometer gemini_flamingos1 :class:`~pypeit.spectrographs.gemini_flamingos.GeminiFLAMINGOS1Spectrograph` GEMINI-S FLAMINGOS `Link `__ MultiSlit False False gemini_flamingos2 :class:`~pypeit.spectrographs.gemini_flamingos.GeminiFLAMINGOS2Spectrograph` GEMINI-S FLAMINGOS `Link `__ MultiSlit True False Flamingos-2 NIR spectrograph diff --git a/doc/pypeit_par.rst b/doc/pypeit_par.rst index d8a7b4a747..d8cc23ea2c 100644 --- a/doc/pypeit_par.rst +++ b/doc/pypeit_par.rst @@ -308,32 +308,33 @@ FlatFieldPar Keywords Class Instantiation: :class:`~pypeit.par.pypeitpar.FlatFieldPar` -========================== ================= ================================= =========== ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ -Key Type Options Default Description -========================== ================= ================================= =========== ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ -``fit_2d_det_response`` bool .. False Set this variable to True if you want to compute and account for the detector response in the flatfield image. Note that ``detector response`` refers to pixel sensitivity variations that primarily depend on (x,y) detector coordinates. In most cases, the default 2D bspline is sufficient to account for detector response (i.e. set this parameter to False). Note that this correction will _only_ be performed for the spectrographs that have a dedicated response correction implemented. Currently,this correction is only implemented for Keck+KCWI. -``illum_iter`` int .. 0 The number of rejection iterations to perform when constructing the slit-illumination profile. No rejection iterations are performed if 0. WARNING: Functionality still being tested. -``illum_rej`` int, float .. 5.0 The sigma threshold used in the rejection iterations used to refine the slit-illumination profile. Rejection iterations are only performed if ``illum_iter > 0``. -``method`` str ``bspline``, ``skip`` ``bspline`` Method used to flat field the data; use skip to skip flat-fielding. Options are: None, bspline, skip -``pixelflat_file`` str .. .. Filename of the image to use for pixel-level field flattening -``pixelflat_max_wave`` int, float .. .. All values of the normalized pixel flat are set to 1 for wavelengths above this value. -``pixelflat_min_wave`` int, float .. .. All values of the normalized pixel flat are set to 1 for wavelengths below this value. -``rej_sticky`` bool .. False Propagate the rejected pixels through the stages of the flat-field fitting (i.e, from the spectral fit, to the spatial fit, and finally to the 2D residual fit). If False, pixels rejected in each stage are included in each subsequent stage. -``saturated_slits`` str ``crash``, ``mask``, ``continue`` ``crash`` Behavior when a slit is encountered with a large fraction of saturated pixels in the flat-field. The options are: 'crash' - Raise an error and halt the data reduction; 'mask' - Mask the slit, meaning no science data will be extracted from the slit; 'continue' - ignore the flat-field correction, but continue with the reduction. -``slit_illum_finecorr`` bool .. True If True, a fine correction to the spatial illumination profile will be performed. The fine correction is a low order 2D polynomial fit to account for a gradual change to the spatial illumination profile as a function of wavelength. -``slit_illum_pad`` int, float .. 5.0 The number of pixels to pad the slit edges when constructing the slit-illumination profile. Single value applied to both edges. -``slit_illum_ref_idx`` int .. 0 The index of a reference slit (0-indexed) used for estimating the relative spectral sensitivity (or the relative blaze). This parameter is only used if ``slit_illum_relative = True``. -``slit_illum_relative`` bool .. False Generate an image of the relative spectral illumination for a multi-slit setup. If you set ``use_specillum = True`` for any of the frames that use the flatfield model, this *must* be set to True. Currently, this is only used for SlicerIFU reductions. -``slit_illum_smooth_npix`` int .. 10 The number of pixels used to determine smoothly varying relative weights is given by ``nspec/slit_illum_smooth_npix``, where nspec is the number of spectral pixels. -``slit_trim`` int, float, tuple .. 3.0 The number of pixels to trim each side of the slit when selecting pixels to use for fitting the spectral response function. Single values are used for both slit edges; a two-tuple can be used to trim the left and right sides differently. -``spat_samp`` int, float .. 5.0 Spatial sampling for slit illumination function. This is the width of the median filter in pixels used to determine the slit illumination function, and thus sets the minimum scale on which the illumination function will have features. -``spec_samp_coarse`` int, float .. 50.0 bspline break point spacing in units of pixels for 2-d bspline-polynomial fit to flat field image residuals. This should be a large number unless you are trying to fit a sky flat with lots of narrow spectral features. -``spec_samp_fine`` int, float .. 1.2 bspline break point spacing in units of pixels for spectral fit to flat field blaze function. -``tweak_slits`` bool .. True Use the illumination flat field to tweak the slit edges. This will work even if illumflatten is set to False -``tweak_slits_maxfrac`` float .. 0.1 If tweak_slit is True, this sets the maximum fractional amount (of a slits width) allowed for trimming each (i.e. left and right) slit boundary, i.e. the default is 10% which means slits would shrink or grow by at most 20% (10% on each side) -``tweak_slits_thresh`` float .. 0.93 If tweak_slits is True, this sets the illumination function threshold used to tweak the slit boundaries based on the illumination flat. It should be a number less than 1.0 -``twod_fit_npoly`` int .. .. Order of polynomial used in the 2D bspline-polynomial fit to flat-field image residuals. The code determines the order of these polynomials to each slit automatically depending on the slit width, which is why the default is None. Alter this paramter at your own risk! -========================== ================= ================================= =========== ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ +========================== ================= ================================= ============= ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ +Key Type Options Default Description +========================== ================= ================================= ============= ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ +``fit_2d_det_response`` bool .. False Set this variable to True if you want to compute and account for the detector response in the flatfield image. Note that ``detector response`` refers to pixel sensitivity variations that primarily depend on (x,y) detector coordinates. In most cases, the default 2D bspline is sufficient to account for detector response (i.e. set this parameter to False). Note that this correction will _only_ be performed for the spectrographs that have a dedicated response correction implemented. Currently,this correction is only implemented for Keck+KCWI. +``illum_iter`` int .. 0 The number of rejection iterations to perform when constructing the slit-illumination profile. No rejection iterations are performed if 0. WARNING: Functionality still being tested. +``illum_rej`` int, float .. 5.0 The sigma threshold used in the rejection iterations used to refine the slit-illumination profile. Rejection iterations are only performed if ``illum_iter > 0``. +``method`` str ``bspline``, ``skip`` ``bspline`` Method used to flat field the data; use skip to skip flat-fielding. Options are: None, bspline, skip +``pixelflat_file`` str .. .. Filename of the image to use for pixel-level field flattening +``pixelflat_max_wave`` int, float .. .. All values of the normalized pixel flat are set to 1 for wavelengths above this value. +``pixelflat_min_wave`` int, float .. .. All values of the normalized pixel flat are set to 1 for wavelengths below this value. +``rej_sticky`` bool .. False Propagate the rejected pixels through the stages of the flat-field fitting (i.e, from the spectral fit, to the spatial fit, and finally to the 2D residual fit). If False, pixels rejected in each stage are included in each subsequent stage. +``saturated_slits`` str ``crash``, ``mask``, ``continue`` ``crash`` Behavior when a slit is encountered with a large fraction of saturated pixels in the flat-field. The options are: 'crash' - Raise an error and halt the data reduction; 'mask' - Mask the slit, meaning no science data will be extracted from the slit; 'continue' - ignore the flat-field correction, but continue with the reduction. +``slit_illum_finecorr`` bool .. True If True, a fine correction to the spatial illumination profile will be performed. The fine correction is a low order 2D polynomial fit to account for a gradual change to the spatial illumination profile as a function of wavelength. +``slit_illum_pad`` int, float .. 5.0 The number of pixels to pad the slit edges when constructing the slit-illumination profile. Single value applied to both edges. +``slit_illum_ref_idx`` int .. 0 The index of a reference slit (0-indexed) used for estimating the relative spectral sensitivity (or the relative blaze). This parameter is only used if ``slit_illum_relative = True``. +``slit_illum_relative`` bool .. False Generate an image of the relative spectral illumination for a multi-slit setup. If you set ``use_specillum = True`` for any of the frames that use the flatfield model, this *must* be set to True. Currently, this is only used for SlicerIFU reductions. +``slit_illum_smooth_npix`` int .. 10 The number of pixels used to determine smoothly varying relative weights is given by ``nspec/slit_illum_smooth_npix``, where nspec is the number of spectral pixels. +``slit_trim`` int, float, tuple .. 3.0 The number of pixels to trim each side of the slit when selecting pixels to use for fitting the spectral response function. Single values are used for both slit edges; a two-tuple can be used to trim the left and right sides differently. +``spat_samp`` int, float .. 5.0 Spatial sampling for slit illumination function. This is the width of the median filter in pixels used to determine the slit illumination function, and thus sets the minimum scale on which the illumination function will have features. +``spec_samp_coarse`` int, float .. 50.0 bspline break point spacing in units of pixels for 2-d bspline-polynomial fit to flat field image residuals. This should be a large number unless you are trying to fit a sky flat with lots of narrow spectral features. +``spec_samp_fine`` int, float .. 1.2 bspline break point spacing in units of pixels for spectral fit to flat field blaze function. +``tweak_method`` str ``threshold``, ``gradient`` ``threshold`` Method used to tweak the slit edges (when "tweak_slits" is set to True). Options include: threshold, gradient. The "threshold" method determines when the left and right slit edges fall below a threshold relative to the peak illumination. The "gradient" method determines where the gradient is the highest at the left and right slit edges. This method performs better when there is systematic vignetting in the spatial direction. +``tweak_slits`` bool .. True Use the illumination flat field to tweak the slit edges. This will work even if illumflatten is set to False +``tweak_slits_maxfrac`` float .. 0.1 If tweak_slit is True, this sets the maximum fractional amount (of a slits width) allowed for trimming each (i.e. left and right) slit boundary, i.e. the default is 10% which means slits would shrink or grow by at most 20% (10% on each side) +``tweak_slits_thresh`` float .. 0.93 If tweak_slits is True, this sets the illumination function threshold used to tweak the slit boundaries based on the illumination flat. It should be a number less than 1.0 +``twod_fit_npoly`` int .. .. Order of polynomial used in the 2D bspline-polynomial fit to flat-field image residuals. The code determines the order of these polynomials to each slit automatically depending on the slit width, which is why the default is None. Alter this paramter at your own risk! +========================== ================= ================================= ============= ================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================ ---- @@ -582,21 +583,21 @@ Collate1DPar Keywords Class Instantiation: :class:`~pypeit.par.pypeitpar.Collate1DPar` -========================= =============== ======= =============================== ================================================================================================================================================================================================================================================================================================================================================================================================================== -Key Type Options Default Description -========================= =============== ======= =============================== ================================================================================================================================================================================================================================================================================================================================================================================================================== -``dry_run`` bool .. False If set, the script will display the matching File and Object Ids but will not flux, coadd or archive. -``exclude_serendip`` bool .. False Whether to exclude SERENDIP objects from collating. -``exclude_slit_trace_bm`` list, str .. A list of slit trace bitmask bits that should be excluded. -``flux`` bool .. False If set, the script will flux calibrate using archived sensfuncs before coadding. -``ignore_flux`` bool .. False If set, the script will only coadd non-fluxed spectra even if flux data is present. Otherwise fluxed spectra are coadded if all spec1ds have been fluxed calibrated. -``match_using`` str .. ``ra/dec`` Determines how 1D spectra are matched as being the same object. Must be either 'pixel' or 'ra/dec'. -``outdir`` str .. ``/home/dusty/work/PypeIt/doc`` The path where all coadded output files and report files will be placed. -``refframe`` str .. .. Perform reference frame correction prior to coadding. Options are: observed, heliocentric, barycentric -``spec1d_outdir`` str .. .. The path where all modified spec1d files are placed. These are only created if flux calibration or refframe correction are asked for. -``tolerance`` str, float, int .. 1.0 The tolerance used when comparing the coordinates of objects. If two objects are within this distance from each other, they are considered the same object. If match_using is 'ra/dec' (the default) this is an angular distance. The defaults units are arcseconds but other units supported by astropy.coordinates.Angle can be used (`e.g.`, '0.003d' or '0h1m30s'). If match_using is 'pixel' this is a float. -``wv_rms_thresh`` float .. .. If set, any objects with a wavelength RMS > this value are skipped, else all wavelength RMS values are accepted. -========================= =============== ======= =============================== ================================================================================================================================================================================================================================================================================================================================================================================================================== +========================= =============== ======= ============================================ ================================================================================================================================================================================================================================================================================================================================================================================================================== +Key Type Options Default Description +========================= =============== ======= ============================================ ================================================================================================================================================================================================================================================================================================================================================================================================================== +``dry_run`` bool .. False If set, the script will display the matching File and Object Ids but will not flux, coadd or archive. +``exclude_serendip`` bool .. False Whether to exclude SERENDIP objects from collating. +``exclude_slit_trace_bm`` list, str .. A list of slit trace bitmask bits that should be excluded. +``flux`` bool .. False If set, the script will flux calibrate using archived sensfuncs before coadding. +``ignore_flux`` bool .. False If set, the script will only coadd non-fluxed spectra even if flux data is present. Otherwise fluxed spectra are coadded if all spec1ds have been fluxed calibrated. +``match_using`` str .. ``ra/dec`` Determines how 1D spectra are matched as being the same object. Must be either 'pixel' or 'ra/dec'. +``outdir`` str .. ``/Users/westfall/Work/packages/pypeit/doc`` The path where all coadded output files and report files will be placed. +``refframe`` str .. .. Perform reference frame correction prior to coadding. Options are: observed, heliocentric, barycentric +``spec1d_outdir`` str .. .. The path where all modified spec1d files are placed. These are only created if flux calibration or refframe correction are asked for. +``tolerance`` str, float, int .. 1.0 The tolerance used when comparing the coordinates of objects. If two objects are within this distance from each other, they are considered the same object. If match_using is 'ra/dec' (the default) this is an angular distance. The defaults units are arcseconds but other units supported by astropy.coordinates.Angle can be used (`e.g.`, '0.003d' or '0h1m30s'). If match_using is 'pixel' this is a float. +``wv_rms_thresh`` float .. .. If set, any objects with a wavelength RMS > this value are skipped, else all wavelength RMS values are accepted. +========================= =============== ======= ============================================ ================================================================================================================================================================================================================================================================================================================================================================================================================== ---- @@ -617,7 +618,7 @@ Key Type Options ``multi_min_SN`` int, float .. 1 Minimum S/N for analyzing sky spectrum for flexure ``spec_maxshift`` int .. 20 Maximum allowed spectral flexure shift in pixels. ``spec_method`` str ``boxcar``, ``slitcen``, ``skip`` ``skip`` Method used to correct for flexure. Use skip for no correction. If slitcen is used, the flexure correction is performed before the extraction of objects (not recommended). Options are: None, boxcar, slitcen, skip -``spectrum`` str .. ``paranal_sky.fits`` Archive sky spectrum to be used for the flexure correction. +``spectrum`` str .. ``paranal_sky.fits`` Archive sky spectrum to be used for the flexure correction. See ``pypeit/data/sky_spec/`` for a list of available sky spectra. If ``model`` is used, a model sky spectrum will be generated using :func:`~pypeit.wavemodel.nearIR_modelsky` and the spectralresolution of the spectrum to be flexure corrected. =================== ========== ======================================================== ==================== ====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== @@ -649,22 +650,22 @@ ReduxPar Keywords Class Instantiation: :class:`~pypeit.par.pypeitpar.ReduxPar` -====================== ============== ======= =============================== ========================================================================================================================================================================================================================================================================================================================================================================================================== -Key Type Options Default Description -====================== ============== ======= =============================== ========================================================================================================================================================================================================================================================================================================================================================================================================== -``calwin`` int, float .. 0 The window of time in hours to search for calibration frames for a science frame -``chk_version`` bool .. True If True enforce strict PypeIt version checking to ensure that all files were created with the current version of PypeIt. If set to False, the code will attempt to read out-of-date files and keep going. Beware (!!) that this can lead to unforeseen bugs that either cause the code to crash or lead to erroneous results. I.e., you really need to know what you are doing if you set this to False! -``detnum`` int, list .. .. Restrict reduction to a list of detector indices. In case of mosaic reduction (currently only available for Gemini/GMOS and Keck/DEIMOS) ``detnum`` should be a list of tuples of the detector indices that are mosaiced together. E.g., for Gemini/GMOS ``detnum`` would be ``[(1,2,3)]`` and for Keck/DEIMOS it would be ``[(1, 5), (2, 6), (3, 7), (4, 8)]`` -``ignore_bad_headers`` bool .. False Ignore bad headers (NOT recommended unless you know it is safe). -``maskIDs`` str, int, list .. .. Restrict reduction to a set of slitmask IDs Example syntax -- ``maskIDs = 818006,818015`` This must be used with detnum (for now). -``qadir`` str .. ``QA`` Directory relative to calling directory to write quality assessment files. -``quicklook`` bool .. False Run a quick look reduction? This is usually good if you want to quickly reduce the data (usually at the telescope in real time) to get an initial estimate of the data quality. -``redux_path`` str .. ``/home/dusty/work/PypeIt/doc`` Path to folder for performing reductions. Default is the current working directory. -``scidir`` str .. ``Science`` Directory relative to calling directory to write science files. -``slitspatnum`` str, list .. .. Restrict reduction to a set of slit DET:SPAT values (closest slit is used). Example syntax -- slitspatnum = DET01:175,DET01:205 or MSC02:2234 If you are re-running the code, (i.e. modifying one slit) you *must* have the precise SPAT_ID index. -``sortroot`` str .. .. A filename given to output the details of the sorted files. If None, the default is the root name of the pypeit file. If off, no output is produced. -``spectrograph`` str .. .. Spectrograph that provided the data to be reduced. See :ref:`instruments` for valid options. -====================== ============== ======= =============================== ========================================================================================================================================================================================================================================================================================================================================================================================================== +====================== ============== ======= ============================================ ========================================================================================================================================================================================================================================================================================================================================================================================================== +Key Type Options Default Description +====================== ============== ======= ============================================ ========================================================================================================================================================================================================================================================================================================================================================================================================== +``calwin`` int, float .. 0 The window of time in hours to search for calibration frames for a science frame +``chk_version`` bool .. True If True enforce strict PypeIt version checking to ensure that all files were created with the current version of PypeIt. If set to False, the code will attempt to read out-of-date files and keep going. Beware (!!) that this can lead to unforeseen bugs that either cause the code to crash or lead to erroneous results. I.e., you really need to know what you are doing if you set this to False! +``detnum`` int, list .. .. Restrict reduction to a list of detector indices. In case of mosaic reduction (currently only available for Gemini/GMOS and Keck/DEIMOS) ``detnum`` should be a list of tuples of the detector indices that are mosaiced together. E.g., for Gemini/GMOS ``detnum`` would be ``[(1,2,3)]`` and for Keck/DEIMOS it would be ``[(1, 5), (2, 6), (3, 7), (4, 8)]`` +``ignore_bad_headers`` bool .. False Ignore bad headers (NOT recommended unless you know it is safe). +``maskIDs`` str, int, list .. .. Restrict reduction to a set of slitmask IDs Example syntax -- ``maskIDs = 818006,818015`` This must be used with detnum (for now). +``qadir`` str .. ``QA`` Directory relative to calling directory to write quality assessment files. +``quicklook`` bool .. False Run a quick look reduction? This is usually good if you want to quickly reduce the data (usually at the telescope in real time) to get an initial estimate of the data quality. +``redux_path`` str .. ``/Users/westfall/Work/packages/pypeit/doc`` Path to folder for performing reductions. Default is the current working directory. +``scidir`` str .. ``Science`` Directory relative to calling directory to write science files. +``slitspatnum`` str, list .. .. Restrict reduction to a set of slit DET:SPAT values (closest slit is used). Example syntax -- slitspatnum = DET01:175,DET01:205 or MSC02:2234 If you are re-running the code, (i.e. modifying one slit) you *must* have the precise SPAT_ID index. +``sortroot`` str .. .. A filename given to output the details of the sorted files. If None, the default is the root name of the pypeit file. If off, no output is produced. +``spectrograph`` str .. .. Spectrograph that provided the data to be reduced. See :ref:`instruments` for valid options. +====================== ============== ======= ============================================ ========================================================================================================================================================================================================================================================================================================================================================================================================== ---- @@ -706,7 +707,6 @@ Key Type Options ``correct_dar`` bool .. True If True, the data will be corrected for differential atmospheric refraction (DAR). ``dec_max`` float .. .. Maximum DEC to use when generating the WCS. If None, the default is maximum DEC based on the WCS of all spaxels. Units should be degrees. ``dec_min`` float .. .. Minimum DEC to use when generating the WCS. If None, the default is minimum DEC based on the WCS of all spaxels. Units should be degrees. -``grating_corr`` bool .. True This option performs a small correction for the relative blaze function of all input frames that have (even slightly) different grating angles, or if you are flux calibrating your science data with a standard star that was observed with a slightly different setup. ``method`` str ``subpixel``, ``ngp`` ``subpixel`` What method should be used to generate the datacube. There are currently two options: (1) "subpixel" (default) - this algorithm divides each pixel in the spec2d frames into subpixels, and assigns each subpixel to a voxel of the datacube. Flux is conserved, but voxels are correlated, and the error spectrum does not account for covariance between adjacent voxels. See also, spec_subpixel and spat_subpixel. (2) "ngp" (nearest grid point) - this algorithm is effectively a 3D histogram. Flux is conserved, voxels are not correlated, however this option suffers the same downsides as any histogram; the choice of bin sizes can change how the datacube appears. This algorithm takes each pixel on the spec2d frame and puts the flux of this pixel into one voxel in the datacube. Depending on the binning used, some voxels may be empty (zero flux) while a neighboring voxel might contain the flux from two spec2d pixels. Note that all spec2d pixels that contribute to the same voxel are inverse variance weighted (e.g. if two pixels have the same variance, the voxel would be assigned the average flux of the two pixels). ``output_filename`` str .. .. If combining multiple frames, this string sets the output filename of the combined datacube. If combine=False, the output filenames will be prefixed with ``spec3d_*`` ``ra_max`` float .. .. Maximum RA to use when generating the WCS. If None, the default is maximum RA based on the WCS of all spaxels. Units should be degrees. @@ -714,13 +714,13 @@ Key Type Options ``reference_image`` str .. .. White light image of a previously combined datacube. The white light image will be used as a reference when calculating the offsets of the input spec2d files. Ideally, the reference image should have the same shape as the data to be combined (i.e. set the ra_min, ra_max etc. params so they are identical to the reference image). ``save_whitelight`` bool .. False Save a white light image of the combined datacube. The output filename will be given by the "output_filename" variable with a suffix "_whitelight". Note that the white light image collapses the flux along the wavelength axis, so some spaxels in the 2D white light image may have different wavelength ranges. To set the wavelength range, use the "whitelight_range" parameter. If combine=False, the individual spec3d files will have a suffix "_whitelight". ``scale_corr`` str .. .. This option performs a small correction for the relative spectral illumination scale of different spec2D files. Specify the relative path+file to the spec2D file that you would like to use for the relative scaling. If you want to perform this correction, it is best to use the spec2d file with the highest S/N sky spectrum. You should choose the same frame for both the standards and science frames. +``sensfile`` str .. .. Filename of a sensitivity function to use to flux calibrate your datacube. The sensitivity function file will also be used to correct the relative scales of the slits. ``skysub_frame`` str .. ``image`` Set the sky subtraction to be implemented. The default behaviour is to subtract the sky using the model that is derived from each individual image (i.e. set this parameter to "image"). To turn off sky subtraction completely, set this parameter to "none" (all lowercase). Finally, if you want to use a different frame for the sky subtraction, specify the relative path+file to the spec2D file that you would like to use for the sky subtraction. The model fit to the sky of the specified frame will be used. Note, the sky and science frames do not need to have the same exposure time; the sky model will be scaled to the science frame based on the relative exposure time. ``slice_subpixel`` int .. 5 When method=subpixel, slice_subpixel sets the subpixellation scale of each IFU slice. The default option is to divide each slice into 5 sub-slices during datacube creation. See also, spec_subpixel and spat_subpixel. ``slit_spec`` bool .. True If the data use slits in one spatial direction, set this to True. If the data uses fibres for all spaxels, set this to False. ``spat_subpixel`` int .. 5 When method=subpixel, spat_subpixel sets the subpixellation scale of each detector pixel in the spatial direction. The total number of subpixels in each pixel is given by spec_subpixel x spat_subpixel. The default option is to divide each spec2d pixel into 25 subpixels during datacube creation. See also, spec_subpixel and slice_subpixel. ``spatial_delta`` float .. .. The spatial size of each spaxel to use when generating the WCS (in arcsec). If None, the default is set by the spectrograph file. ``spec_subpixel`` int .. 5 When method=subpixel, spec_subpixel sets the subpixellation scale of each detector pixel in the spectral direction. The total number of subpixels in each pixel is given by spec_subpixel x spat_subpixel. The default option is to divide each spec2d pixel into 25 subpixels during datacube creation. See also, spat_subpixel and slice_subpixel. -``standard_cube`` str .. .. Filename of a standard star datacube. This cube will be used to correct the relative scales of the slits, and to flux calibrate the science datacube. ``wave_delta`` float .. .. The wavelength step to use when generating the WCS (in Angstroms). If None, the default is set by the wavelength solution. ``wave_max`` float .. .. Maximum wavelength to use when generating the WCS. If None, the default is maximum wavelength based on the WCS of all spaxels. Units should be Angstroms. ``wave_min`` float .. .. Minimum wavelength to use when generating the WCS. If None, the default is minimum wavelength based on the WCS of all spaxels. Units should be Angstroms. @@ -864,43 +864,44 @@ ProcessImagesPar Keywords Class Instantiation: :class:`~pypeit.par.pypeitpar.ProcessImagesPar` -======================== ================================================ =================================================================== ============================= ============================================================================================================================================================================================================================================================================================================================================================ -Key Type Options Default Description -======================== ================================================ =================================================================== ============================= ============================================================================================================================================================================================================================================================================================================================================================ -``apply_gain`` bool .. True Convert the ADUs to electrons using the detector gain -``clip`` bool .. True Perform sigma clipping when combining. Only used with combine=mean -``comb_sigrej`` float .. .. Sigma-clipping level for when clip=True; Use None for automatic limit (recommended). -``combine`` str ``median``, ``mean`` ``mean`` Method used to combine multiple frames. Options are: median, mean -``dark_expscale`` bool .. False If designated dark frames are used and have a different exposure time than the science frames, scale the counts by the by the ratio in the exposure times to adjust the dark counts for the difference in exposure time. WARNING: You should always take dark frames that have the same exposure time as your science frames, so use this option with care! -``empirical_rn`` bool .. False If True, use the standard deviation in the overscan region to measure an empirical readnoise to use in the noise model. -``grow`` int, float .. 1.5 Factor by which to expand regions with cosmic rays detected by the LA cosmics routine. -``lamaxiter`` int .. 1 Maximum number of iterations for LA cosmics routine. -``mask_cr`` bool .. False Identify CRs and mask them -``n_lohi`` list .. 0, 0 Number of pixels to reject at the lowest and highest ends of the distribution; i.e., n_lohi = low, high. Use None for no limit. -``noise_floor`` float .. 0.0 Impose a noise floor by adding the provided fraction of the bias- and dark-subtracted electron counts to the error budget. E.g., a value of 0.01 means that the S/N of the counts in the image will never be greater than 100. -``objlim`` int, float .. 3.0 Object detection limit in LA cosmics routine -``orient`` bool .. True Orient the raw image into the PypeIt frame -``overscan_method`` str ``chebyshev``, ``polynomial``, ``savgol``, ``median``, ``odd_even`` ``savgol`` Method used to fit the overscan. Options are: chebyshev, polynomial, savgol, median, odd_even Note: Method "polynomial" is identical to "chebyshev"; the former is deprecated and will be removed. -``overscan_par`` int, list .. 5, 65 Parameters for the overscan subtraction. For 'chebyshev' or 'polynomial', set overcan_par = order; for 'savgol', set overscan_par = order, window size ; for 'median', set overscan_par = None or omit the keyword. -``rmcompact`` bool .. True Remove compact detections in LA cosmics routine -``satpix`` str ``reject``, ``force``, ``nothing`` ``reject`` Handling of saturated pixels. Options are: reject, force, nothing -``scattlight`` :class:`~pypeit.par.pypeitpar.ScatteredLightPar` .. `ScatteredLightPar Keywords`_ Scattered light subtraction parameters. -``shot_noise`` bool .. True Use the bias- and dark-subtracted image to calculate and include electron count shot noise in the image processing error budget -``sigclip`` int, float .. 4.5 Sigma level for rejection in LA cosmics routine -``sigfrac`` int, float .. 0.3 Fraction for the lower clipping threshold in LA cosmics routine. -``spat_flexure_correct`` bool .. False Correct slits, illumination flat, etc. for flexure -``spat_flexure_maxlag`` int .. 20 Maximum of possible spatial flexure correction, in pixels -``subtract_continuum`` bool .. False Subtract off the continuum level from an image. This parameter should only be set to True to combine arcs with multiple different lamps. For all other cases, this parameter should probably be False. -``subtract_scattlight`` bool .. False Subtract off the scattered light from an image. This parameter should only be set to True for spectrographs that have dedicated methods to subtract scattered light. For all other cases, this parameter should be False. -``trim`` bool .. True Trim the image to the detector supplied region -``use_biasimage`` bool .. True Use a bias image. If True, one or more must be supplied in the PypeIt file. -``use_darkimage`` bool .. False Subtract off a dark image. If True, one or more darks must be provided. -``use_illumflat`` bool .. True Use the illumination flat to correct for the illumination profile of each slit. -``use_overscan`` bool .. True Subtract off the overscan. Detector *must* have one or code will crash. -``use_pattern`` bool .. False Subtract off a detector pattern. This pattern is assumed to be sinusoidal along one direction, with a frequency that is constant across the detector. -``use_pixelflat`` bool .. True Use the pixel flat to make pixel-level corrections. A pixelflat image must be provied. -``use_specillum`` bool .. False Use the relative spectral illumination profiles to correct the spectral illumination profile of each slit. This is primarily used for slicer IFUs. To use this, you must set ``slit_illum_relative=True`` in the ``flatfield`` parameter set! -======================== ================================================ =================================================================== ============================= ============================================================================================================================================================================================================================================================================================================================================================ +======================== ================================================ =================================================================== ============================= ======================================================================================================================================================================================================================================================================================================================================================================================== +Key Type Options Default Description +======================== ================================================ =================================================================== ============================= ======================================================================================================================================================================================================================================================================================================================================================================================== +``apply_gain`` bool .. True Convert the ADUs to electrons using the detector gain +``clip`` bool .. True Perform sigma clipping when combining. Only used with combine=mean +``comb_sigrej`` float .. .. Sigma-clipping level for when clip=True; Use None for automatic limit (recommended). +``combine`` str ``median``, ``mean`` ``mean`` Method used to combine multiple frames. Options are: median, mean +``correct_nonlinear`` list .. .. Correct for non-linear response of the detector. If None, no correction is performed. If a list, then the list should be the non-linear correction parameter (alpha), where the functional form is given by Ct = Cm (1 + alpha x Cm), with Ct and Cm the true and measured counts. This parameter is usually hard-coded for a given spectrograph, and should otherwise be left as None. +``dark_expscale`` bool .. False If designated dark frames are used and have a different exposure time than the science frames, scale the counts by the by the ratio in the exposure times to adjust the dark counts for the difference in exposure time. WARNING: You should always take dark frames that have the same exposure time as your science frames, so use this option with care! +``empirical_rn`` bool .. False If True, use the standard deviation in the overscan region to measure an empirical readnoise to use in the noise model. +``grow`` int, float .. 1.5 Factor by which to expand regions with cosmic rays detected by the LA cosmics routine. +``lamaxiter`` int .. 1 Maximum number of iterations for LA cosmics routine. +``mask_cr`` bool .. False Identify CRs and mask them +``n_lohi`` list .. 0, 0 Number of pixels to reject at the lowest and highest ends of the distribution; i.e., n_lohi = low, high. Use None for no limit. +``noise_floor`` float .. 0.0 Impose a noise floor by adding the provided fraction of the bias- and dark-subtracted electron counts to the error budget. E.g., a value of 0.01 means that the S/N of the counts in the image will never be greater than 100. +``objlim`` int, float .. 3.0 Object detection limit in LA cosmics routine +``orient`` bool .. True Orient the raw image into the PypeIt frame +``overscan_method`` str ``chebyshev``, ``polynomial``, ``savgol``, ``median``, ``odd_even`` ``savgol`` Method used to fit the overscan. Options are: chebyshev, polynomial, savgol, median, odd_even Note: Method "polynomial" is identical to "chebyshev"; the former is deprecated and will be removed. +``overscan_par`` int, list .. 5, 65 Parameters for the overscan subtraction. For 'chebyshev' or 'polynomial', set overcan_par = order; for 'savgol', set overscan_par = order, window size ; for 'median', set overscan_par = None or omit the keyword. +``rmcompact`` bool .. True Remove compact detections in LA cosmics routine +``satpix`` str ``reject``, ``force``, ``nothing`` ``reject`` Handling of saturated pixels. Options are: reject, force, nothing +``scattlight`` :class:`~pypeit.par.pypeitpar.ScatteredLightPar` .. `ScatteredLightPar Keywords`_ Scattered light subtraction parameters. +``shot_noise`` bool .. True Use the bias- and dark-subtracted image to calculate and include electron count shot noise in the image processing error budget +``sigclip`` int, float .. 4.5 Sigma level for rejection in LA cosmics routine +``sigfrac`` int, float .. 0.3 Fraction for the lower clipping threshold in LA cosmics routine. +``spat_flexure_correct`` bool .. False Correct slits, illumination flat, etc. for flexure +``spat_flexure_maxlag`` int .. 20 Maximum of possible spatial flexure correction, in pixels +``subtract_continuum`` bool .. False Subtract off the continuum level from an image. This parameter should only be set to True to combine arcs with multiple different lamps. For all other cases, this parameter should probably be False. +``subtract_scattlight`` bool .. False Subtract off the scattered light from an image. This parameter should only be set to True for spectrographs that have dedicated methods to subtract scattered light. For all other cases, this parameter should be False. +``trim`` bool .. True Trim the image to the detector supplied region +``use_biasimage`` bool .. True Use a bias image. If True, one or more must be supplied in the PypeIt file. +``use_darkimage`` bool .. False Subtract off a dark image. If True, one or more darks must be provided. +``use_illumflat`` bool .. True Use the illumination flat to correct for the illumination profile of each slit. +``use_overscan`` bool .. True Subtract off the overscan. Detector *must* have one or code will crash. +``use_pattern`` bool .. False Subtract off a detector pattern. This pattern is assumed to be sinusoidal along one direction, with a frequency that is constant across the detector. +``use_pixelflat`` bool .. True Use the pixel flat to make pixel-level corrections. A pixelflat image must be provied. +``use_specillum`` bool .. False Use the relative spectral illumination profiles to correct the spectral illumination profile of each slit. This is primarily used for slicer IFUs. To use this, you must set ``slit_illum_relative=True`` in the ``flatfield`` parameter set! +======================== ================================================ =================================================================== ============================= ======================================================================================================================================================================================================================================================================================================================================================================================== ---- @@ -1047,6 +1048,98 @@ these in the PypeIt file, you would be reproducing the effect of the `default_pypeit_par` method specific to each derived :class:`~pypeit.spectrographs.spectrograph.Spectrograph` class. +.. _instr_par-aat_uhrf: + +AAT UHRF (``aat_uhrf``) +----------------------- +Alterations to the default parameters are: + +.. code-block:: ini + + [rdx] + spectrograph = aat_uhrf + [calibrations] + [[biasframe]] + [[[process]]] + combine = median + use_biasimage = False + shot_noise = False + use_pixelflat = False + use_illumflat = False + [[darkframe]] + [[[process]]] + mask_cr = True + use_pixelflat = False + use_illumflat = False + [[arcframe]] + exprng = None, 60.0, + [[[process]]] + use_pixelflat = False + use_illumflat = False + [[tiltframe]] + exprng = None, 60.0, + [[[process]]] + use_pixelflat = False + use_illumflat = False + [[pixelflatframe]] + [[[process]]] + satpix = nothing + use_pixelflat = False + use_illumflat = False + [[alignframe]] + [[[process]]] + satpix = nothing + use_pixelflat = False + use_illumflat = False + [[traceframe]] + exprng = None, 60.0, + [[[process]]] + use_pixelflat = False + use_illumflat = False + [[illumflatframe]] + [[[process]]] + satpix = nothing + use_pixelflat = False + use_illumflat = False + [[lampoffflatsframe]] + [[[process]]] + satpix = nothing + use_pixelflat = False + use_illumflat = False + [[scattlightframe]] + [[[process]]] + satpix = nothing + use_pixelflat = False + use_illumflat = False + [[skyframe]] + [[[process]]] + mask_cr = True + noise_floor = 0.01 + [[standardframe]] + [[[process]]] + mask_cr = True + noise_floor = 0.01 + [[wavelengths]] + lamps = ThAr, + n_final = 3 + [[slitedges]] + sync_predict = nearest + bound_detector = True + [[tilts]] + spat_order = 4 + spec_order = 1 + [scienceframe] + exprng = 61, None, + [[process]] + mask_cr = True + sigclip = 10.0 + noise_floor = 0.01 + [reduce] + [[skysub]] + bspline_spacing = 3.0 + no_poly = True + user_regions = :10,75: + .. _instr_par-bok_bc: BOK BC (``bok_bc``) @@ -2031,12 +2124,11 @@ Alterations to the default parameters are: noise_floor = 0.01 use_illumflat = False [[flatfield]] + tweak_method = gradient tweak_slits_thresh = 0.0 tweak_slits_maxfrac = 0.0 slit_trim = 2 slit_illum_finecorr = False - [[slitedges]] - pad = 2 [[tilts]] spat_order = 1 spec_order = 1 @@ -2061,8 +2153,6 @@ Alterations to the default parameters are: [[extraction]] model_full_slit = True skip_extraction = True - [[cube]] - grating_corr = False [flexure] spec_maxshift = 0 [sensfunc] @@ -2152,6 +2242,9 @@ Alterations to the default parameters are: mask_cr = True noise_floor = 0.01 [[flatfield]] + tweak_method = gradient + tweak_slits_thresh = 0.0 + tweak_slits_maxfrac = 0.0 slit_illum_finecorr = False [[wavelengths]] method = full_template @@ -3023,18 +3116,16 @@ Alterations to the default parameters are: noise_floor = 0.01 [[flatfield]] spec_samp_coarse = 20.0 + tweak_method = gradient tweak_slits_thresh = 0.0 tweak_slits_maxfrac = 0.0 slit_illum_relative = True slit_illum_ref_idx = 14 - slit_illum_smooth_npix = 5 - fit_2d_det_response = True [[wavelengths]] fwhm_spat_order = 2 [[slitedges]] edge_thresh = 5 fit_order = 4 - pad = 2 [scienceframe] [[process]] mask_cr = True @@ -3085,16 +3176,18 @@ Alterations to the default parameters are: use_pattern = True [[arcframe]] [[[process]]] + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, use_pixelflat = False use_illumflat = False [[tiltframe]] [[[process]]] + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, use_pixelflat = False use_illumflat = False [[pixelflatframe]] [[[process]]] - combine = median satpix = nothing + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, use_pixelflat = False use_illumflat = False subtract_scattlight = True @@ -3112,6 +3205,7 @@ Alterations to the default parameters are: [[illumflatframe]] [[[process]]] satpix = nothing + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, use_illumflat = False use_pattern = True subtract_scattlight = True @@ -3132,32 +3226,32 @@ Alterations to the default parameters are: [[standardframe]] [[[process]]] mask_cr = True + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, noise_floor = 0.01 use_pattern = True [[flatfield]] spec_samp_coarse = 20.0 spat_samp = 1.0 + tweak_method = gradient tweak_slits_thresh = 0.0 tweak_slits_maxfrac = 0.0 slit_illum_relative = True slit_illum_ref_idx = 14 - slit_illum_smooth_npix = 5 fit_2d_det_response = True [[wavelengths]] fwhm_spat_order = 2 [[slitedges]] edge_thresh = 5 fit_order = 4 - pad = 2 [scienceframe] [[process]] mask_cr = True sigclip = 4.0 objlim = 1.5 + correct_nonlinear = -1.4e-07, -1.4e-07, -1.2e-07, -1.8e-07, noise_floor = 0.01 use_specillum = True use_pattern = True - subtract_scattlight = True [[[scattlight]]] finecorr_method = median [reduce] diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index 8ec9e4edce..1d8b28c11e 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -29,12 +29,13 @@ Script Changes expansion of and changes to the cache system. - Added ``pypeit_clean_cache`` script to facilitate both viewing and removing files in the cache. - - A new script, called `pypeit_extract_datacube`, allows 1D spectra of point sources to be extracted from datacubes. - The sensitivity function is now generated outside of datacube generation. - The `grating_corr` column is now used to select the correct grating correction file for each spec2d file when generating the datacube. +- Treatment of file names is now more formal. Compression signatures are now + considered, and filename matching is now more strict. Datamodel Changes ----------------- diff --git a/pypeit/core/datacube.py b/pypeit/core/datacube.py index 3f9625ba9b..50a2a9959a 100644 --- a/pypeit/core/datacube.py +++ b/pypeit/core/datacube.py @@ -223,7 +223,7 @@ def extract_point_source(wave, flxcube, ivarcube, bpmcube, wcscube, exptime, Returns ------- - sobjs : `pypeit.specobjs.SpecObjs`_ + sobjs : :class:`pypeit.specobjs.SpecObjs` SpecObjs object containing the extracted spectrum """ if whitelight_range is None: diff --git a/pypeit/flatfield.py b/pypeit/flatfield.py index 432ed4d469..646f659c1c 100644 --- a/pypeit/flatfield.py +++ b/pypeit/flatfield.py @@ -1584,8 +1584,9 @@ def spectral_illumination(self, gpm=None, debug=False): smooth_npix=self.flatpar['slit_illum_smooth_npix'], debug=debug) - def tweak_slit_edges(self, left, right, spat_coo, norm_flat, method='threshold', thresh=0.93, maxfrac=0.1, debug=False): - """ + def tweak_slit_edges(self, left, right, spat_coo, norm_flat, method='threshold', thresh=0.93, + maxfrac=0.1, debug=False): + r""" Tweak the slit edges based on the normalized slit illumination profile. Args: @@ -1606,12 +1607,15 @@ def tweak_slit_edges(self, left, right, spat_coo, norm_flat, method='threshold', profile. Shape is :math:`(N_{\rm flat},)`. method (:obj:`str`, optional): Method to use for tweaking the slit edges. Options are: - - 'threshold': Use the threshold to set the slit edge - and then shift it to the left or right based on the - illumination profile. - - 'gradient': Use the gradient of the illumination - profile to set the slit edge and then shift it to - the left or right based on the illumination profile. + + - ``'threshold'``: Use the threshold to set the slit edge + and then shift it to the left or right based on the + illumination profile. + + - ``'gradient'``: Use the gradient of the illumination + profile to set the slit edge and then shift it to the left + or right based on the illumination profile. + thresh (:obj:`float`, optional): Threshold of the normalized flat profile at which to place the two slit edges. @@ -1630,13 +1634,14 @@ def tweak_slit_edges(self, left, right, spat_coo, norm_flat, method='threshold', tuple: Returns six objects: - The threshold used to set the left edge - - The fraction of the slit that the left edge is shifted to - the right + - The fraction of the slit that the left edge is shifted to the + right - The adjusted left edge - The threshold used to set the right edge - - The fraction of the slit that the right edge is shifted to - the left + - The fraction of the slit that the right edge is shifted to the + left - The adjusted right edge + """ # TODO :: Since this is just a wrapper, and not really "core", maybe it should be moved to pypeit.flatfield? # Tweak the edges via the specified method diff --git a/pypeit/images/combineimage.py b/pypeit/images/combineimage.py index 635cb4905d..1e20c37710 100644 --- a/pypeit/images/combineimage.py +++ b/pypeit/images/combineimage.py @@ -22,9 +22,10 @@ class CombineImage: Process and combine detector images. Args: - rawImages (:obj:`list`, :class:`~pypeit.images.pypeitimage.PypeItImage): - Either a single :class:`~pypeit.images.pypeitimage.PypeItImage` object or a list of one or more - of these objects to be combined into a an image. + rawImages (:obj:`list`, :class:`~pypeit.images.pypeitimage.PypeItImage`): + Either a single :class:`~pypeit.images.pypeitimage.PypeItImage` + object or a list of one or more of these objects to be combined into + an image. par (:class:`~pypeit.par.pypeitpar.ProcessImagesPar`): Parameters that dictate the processing of the images. diff --git a/pypeit/scripts/chk_for_calibs.py b/pypeit/scripts/chk_for_calibs.py index ed3000d992..9269529fa7 100644 --- a/pypeit/scripts/chk_for_calibs.py +++ b/pypeit/scripts/chk_for_calibs.py @@ -21,8 +21,11 @@ def get_parser(cls, width=None): parser.add_argument('-s', '--spectrograph', default=None, type=str, help='A valid spectrograph identifier: {0}'.format( ', '.join(available_spectrographs))) - parser.add_argument('-e', '--extension', default='.fits', - help='File extension; compression indicators (e.g. .gz) not required.') + parser.add_argument('-e', '--extension', default=None, + help='File extension to use. Must include the period (e.g., ".fits") ' + 'and it must be one of the allowed extensions for this ' + 'spectrograph. If None, root directory will be searched for ' + 'all files with any of the allowed extensions.') parser.add_argument('--save_setups', default=False, action='store_true', help='If not toggled, remove setup_files/ folder and its files.') return parser diff --git a/pypeit/scripts/coadd_1dspec.py b/pypeit/scripts/coadd_1dspec.py index 7763f9b905..98306e1126 100644 --- a/pypeit/scripts/coadd_1dspec.py +++ b/pypeit/scripts/coadd_1dspec.py @@ -22,69 +22,6 @@ from pypeit.spectrographs.util import load_spectrograph -## TODO: This is basically the exact same code as read_fluxfile in the fluxing -## script. Consolidate them? Make this a standard method in parse or io. -#def read_coaddfile(ifile): -# """ -# Read a ``PypeIt`` coadd1d file, akin to a standard PypeIt file. -# -# The top is a config block that sets ParSet parameters. The name of the -# spectrograph is required. -# -# Args: -# ifile (:obj:`str`): -# Name of the coadd file -# -# Returns: -# :obj:`tuple`: Three objects are returned: a :obj:`list` with the -# configuration entries used to modify the relevant -# :class:`~pypeit.par.parset.ParSet` parameters, a :obj:`list` the names -# of spec1d files to be coadded, and a :obj:`list` with the object IDs -# aligned with each of the spec1d files. -# """ -# # Read in the pypeit reduction file -# msgs.info('Loading the coadd1d file') -# lines = inputfiles.read_pypeit_file_lines(ifile) -# is_config = np.ones(len(lines), dtype=bool) -# -# -# # Parse the fluxing block -# spec1dfiles = [] -# objids_in = [] -# s, e = inputfiles.InputFile.find_block(lines, 'coadd1d') -# if s >= 0 and e < 0: -# msgs.error("Missing 'coadd1d end' in {0}".format(ifile)) -# elif (s < 0) or (s==e): -# msgs.error("Missing coadd1d read or [coadd1d] block in in {0}. Check the input format for the .coadd1d file".format(ifile)) -# else: -# for ctr, line in enumerate(lines[s:e]): -# prs = line.split(' ') -# spec1dfiles.append(prs[0]) -# if ctr == 0 and len(prs) != 2: -# msgs.error('Invalid format for .coadd1d file.' + msgs.newline() + -# 'You must have specify a spec1dfile and objid on the first line of the coadd1d block') -# if len(prs) > 1: -# objids_in.append(prs[1]) -# is_config[s-1:e+1] = False -# -# # Chck the sizes of the inputs -# nspec = len(spec1dfiles) -# if len(objids_in) == 1: -# objids = nspec*objids_in -# elif len(objids_in) == nspec: -# objids = objids_in -# else: -# msgs.error('Invalid format for .flux file.' + msgs.newline() + -# 'You must specify a single objid on the first line of the coadd1d block,' + msgs.newline() + -# 'or specify am objid for every spec1dfile in the coadd1d block.' + msgs.newline() + -# 'Run pypeit_coadd_1dspec --help for information on the format') -# # Construct config to get spectrograph -# cfg_lines = list(lines[is_config]) -# -# # Return -# return cfg_lines, spec1dfiles, objids - - def build_coadd_file_name(spec1dfiles, spectrograph): """Build the output file name for coadding. The filename convention is coadd1d___.fits or @@ -116,6 +53,7 @@ def build_coadd_file_name(spec1dfiles, spectrograph): path = os.path.dirname(os.path.abspath(spec1dfiles[0])) return os.path.join(path, f'coadd1d_{target}_{instrument_name}_{date_portion}.fits') + class CoAdd1DSpec(scriptbase.ScriptBase): @classmethod diff --git a/pypeit/scripts/multislit_flexure.py b/pypeit/scripts/multislit_flexure.py index 98e836196b..1691361687 100644 --- a/pypeit/scripts/multislit_flexure.py +++ b/pypeit/scripts/multislit_flexure.py @@ -18,55 +18,6 @@ from pypeit.scripts import scriptbase -#def read_flexfile(ifile): -# """ -# Read a ``PypeIt`` flexure file, akin to a standard ``PypeIt`` file. -# -# The top is a config block that sets ParSet parameters. -# -# Args: -# ifile (:obj:`str`): -# Name of the flexure file -# -# Returns: -# :obj:`tuple`: Two objects are returned: a :obj:`list` with the -# configuration entries used to modify the relevant -# :class:`~pypeit.par.parset.ParSet` parameters and a :obj:`list` with the -# names of spec1d files to be flexure corrected. -# """ -# # Read in the pypeit reduction file -# msgs.info('Loading the flexure file') -# lines = inputfiles.read_pypeit_file_lines(ifile) -# is_config = np.ones(len(lines), dtype=bool) -# -# # Parse the fluxing block -# spec1dfiles = [] -# objids_in = [] -# s, e = inputfiles.InputFile.find_block(lines, 'flexure') -# if s >= 0 and e < 0: -# msgs.error("Missing 'flexure end' in {0}".format(ifile)) -# elif (s < 0) or (s == e): -# msgs.error( -# "Missing flexure read block in {0}. Check the input format for the .flex file".format(ifile)) -# else: -# for ctr, line in enumerate(lines[s:e]): -# prs = line.split(' ') -# spec1dfiles.append(prs[0]) -# if len(prs) > 1: -# msgs.error('Invalid format for .flex file.' + msgs.newline() + -# 'You must specify only spec1dfiles in the block ') -# is_config[s-1:e+1] = False -# -# # Chck the sizes of the inputs -# nspec = len(spec1dfiles) -# -# # Construct config to get spectrograph -# cfg_lines = list(lines[is_config]) -# -# # Return -# return cfg_lines, spec1dfiles - - # TODO: Maybe not a good idea to name this script the same as the # flexure.MultiSlitFlexure class, but it is technically okay... class MultiSlitFlexure(scriptbase.ScriptBase): diff --git a/pypeit/scripts/obslog.py b/pypeit/scripts/obslog.py index 693b670a0c..6e1e7a7657 100644 --- a/pypeit/scripts/obslog.py +++ b/pypeit/scripts/obslog.py @@ -65,8 +65,11 @@ def get_parser(cls, width=None): parser.add_argument('-s', '--sort', default='mjd', type=str, help='Metadata keyword (pypeit-specific) to use to sort the output ' 'table.') - parser.add_argument('-e', '--extension', default='.fits', - help='File extension; compression indicators (e.g. .gz) not required.') + parser.add_argument('-e', '--extension', default=None, + help='File extension to use. Must include the period (e.g., ".fits") ' + 'and it must be one of the allowed extensions for this ' + 'spectrograph. If None, root directory will be searched for ' + 'all files with any of the allowed extensions.') parser.add_argument('-d', '--output_path', default='current working directory', help='Path to top-level output directory.') parser.add_argument('-o', '--overwrite', default=False, action='store_true', @@ -115,8 +118,7 @@ def main(args): f'argument.') # Generate the metadata table - ps = PypeItSetup.from_file_root(args.root, args.spec, - extension=args.extension) + ps = PypeItSetup.from_file_root(args.root, args.spec, extension=args.extension) ps.run(setup_only=True, # This allows for bad headers groupings=args.groupings, clean_config=args.bad_frames) diff --git a/pypeit/scripts/setup.py b/pypeit/scripts/setup.py index 9de645baa3..f417caf172 100644 --- a/pypeit/scripts/setup.py +++ b/pypeit/scripts/setup.py @@ -28,8 +28,11 @@ def get_parser(cls, width=None): 'directory (e.g., /data/Kast) or the search string up through ' 'the wildcard (.e.g, /data/Kast/b). Use the --extension option ' 'to set the types of files to search for.') - parser.add_argument('-e', '--extension', default='.fits', - help='File extension; compression indicators (e.g. .gz) not required.') + parser.add_argument('-e', '--extension', default=None, + help='File extension to use. Must include the period (e.g., ".fits") ' + 'and it must be one of the allowed extensions for this ' + 'spectrograph. If None, root directory will be searched for ' + 'all files with any of the allowed extensions.') parser.add_argument('-d', '--output_path', default='current working directory', help='Path to top-level output directory.') parser.add_argument('-o', '--overwrite', default=False, action='store_true', diff --git a/pypeit/scripts/setup_gui.py b/pypeit/scripts/setup_gui.py index d864eb0372..b8925be7e6 100644 --- a/pypeit/scripts/setup_gui.py +++ b/pypeit/scripts/setup_gui.py @@ -27,8 +27,11 @@ def get_parser(cls, width=None): 'the wildcard (.e.g, /data/Kast/b). Use the --extension option ' 'to set the types of files to search for. Default is the ' 'current working directory.') - parser.add_argument('-e', '--extension', default='.fits', - help='File extension; compression indicators (e.g. .gz) not required.') + parser.add_argument('-e', '--extension', default=None, + help='File extension to use. Must include the period (e.g., ".fits") ' + 'and it must be one of the allowed extensions for this ' + 'spectrograph. If None, root directory will be searched for ' + 'all files with any of the allowed extensions.') parser.add_argument('-l', '--logfile', type=str, default=None, help="Write the PypeIt logs to the given file. If the file exists it will be renamed.") parser.add_argument('-v', '--verbosity', type=int, default=2, diff --git a/pypeit/spectrographs/aat_uhrf.py b/pypeit/spectrographs/aat_uhrf.py index 52d0a00d67..ea71c1ed10 100644 --- a/pypeit/spectrographs/aat_uhrf.py +++ b/pypeit/spectrographs/aat_uhrf.py @@ -49,7 +49,7 @@ def get_detector_par(self, det, hdu=None): Object with the detector metadata. """ # Retrieve the binning - binning = self.compound_meta(self.get_headarr(hdu), "binning") + binning = '1,1' if hdu is None else self.compound_meta(self.get_headarr(hdu), "binning") dsec = 1 + 1024//int(binning.split(',')[0]) # Detector 1 detector_dict = dict( diff --git a/pypeit/spectrographs/spectrograph.py b/pypeit/spectrographs/spectrograph.py index bc4aa24fa5..24d38b22c9 100644 --- a/pypeit/spectrographs/spectrograph.py +++ b/pypeit/spectrographs/spectrograph.py @@ -318,9 +318,9 @@ def _check_extensions(self, filename): """ if self.allowed_extensions is not None: _filename = Path(filename).absolute() - if _filename.suffix not in self.allowed_extensions: + if not any([_filename.name.endswith(ext) for ext in self.allowed_extensions]): msgs.error(f'The input file ({_filename.name}) does not have a recognized ' - f'extension ({_filename.suffix}). The allowed extensions for ' + f'extension. The allowed extensions for ' f'{self.name} include {",".join(self.allowed_extensions)}.') def _check_telescope(self): diff --git a/pypeit/tests/test_calibrations.py b/pypeit/tests/test_calibrations.py index 3705674b59..52ac1958ac 100644 --- a/pypeit/tests/test_calibrations.py +++ b/pypeit/tests/test_calibrations.py @@ -1,13 +1,10 @@ -""" -Module to run tests on FlatField class -Requires files in Development suite and an Environmental variable -""" from pathlib import Path -import os import yaml import pytest import shutil +from IPython import embed + import numpy as np from pypeit import dataPaths @@ -16,9 +13,8 @@ from pypeit.images import buildimage from pypeit.par import pypeitpar from pypeit.spectrographs.util import load_spectrograph -from IPython import embed -from pypeit.tests.tstutils import dummy_fitstbl, data_output_path +from pypeit.tests.tstutils import data_output_path @pytest.fixture def fitstbl(): diff --git a/pypeit/tests/test_io.py b/pypeit/tests/test_io.py index 95d03abb14..2a6f226297 100644 --- a/pypeit/tests/test_io.py +++ b/pypeit/tests/test_io.py @@ -48,5 +48,5 @@ def test_grab_rawfiles(): _raw_files = inputfiles.grab_rawfiles(raw_paths=[str(root)], extension='.fits.gz') assert len(_raw_files) == 9, 'Found the wrong number of files' - assert all([str(root / f) in _raw_files for f in tbl['filename']]), 'Missing expected files' + assert all([root / f in _raw_files for f in tbl['filename']]), 'Missing expected files' diff --git a/pypeit/tests/test_metadata.py b/pypeit/tests/test_metadata.py index 048191cc3f..467daa44bf 100644 --- a/pypeit/tests/test_metadata.py +++ b/pypeit/tests/test_metadata.py @@ -30,7 +30,7 @@ def test_read_combid(): # Generate the pypeit file with the comb_id droot = tstutils.data_output_path('b') pargs = Setup.parse_args(['-r', droot, '-s', 'shane_kast_blue', '-c', 'all', '-b', - '--extension', 'fits.gz', '--output_path', f'{config_dir.parent}']) + '--output_path', f'{config_dir.parent}']) Setup.main(pargs) pypeit_file = config_dir / 'shane_kast_blue_A.pypeit' diff --git a/pypeit/tests/test_setups.py b/pypeit/tests/test_setups.py index e4356968e1..5759072024 100644 --- a/pypeit/tests/test_setups.py +++ b/pypeit/tests/test_setups.py @@ -63,12 +63,12 @@ def test_run_setup(): droot = tstutils.data_output_path('b') odir = Path(tstutils.data_output_path('')).absolute() / 'shane_kast_blue_A' pargs = Setup.parse_args(['-r', droot, '-s', 'shane_kast_blue', '-c', 'all', - '--extension', 'fits.gz', '--output_path', f'{odir.parent}']) + '--output_path', f'{odir.parent}']) Setup.main(pargs) # Fails because name of spectrograph is wrong pargs2 = Setup.parse_args(['-r', droot, '-s', 'shane_kast_blu', '-c', 'all', - '--extension', 'fits.gz', '--output_path', f'{odir.parent}']) + '--output_path', f'{odir.parent}']) with pytest.raises(ValueError): Setup.main(pargs2) From 348743f6bfb6d14a4803ed54391869a9b34fe26c Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Tue, 13 Aug 2024 09:22:58 -0700 Subject: [PATCH 26/35] doc update --- doc/cookbook.rst | 3 ++- doc/setup.rst | 29 +++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/cookbook.rst b/doc/cookbook.rst index 915aed4865..19b397281e 100644 --- a/doc/cookbook.rst +++ b/doc/cookbook.rst @@ -70,7 +70,8 @@ what we recommend: - We will refer to that folder as ``RAWDIR`` The raw images can be gzip-compressed, although this means opening files will be -slower. +slower. See :ref:`setup-file-searching` for specific comments about the files +in your raw directory. A word on calibration data -------------------------- diff --git a/doc/setup.rst b/doc/setup.rst index 2a046b17e5..523ed2290d 100644 --- a/doc/setup.rst +++ b/doc/setup.rst @@ -22,6 +22,27 @@ preparatory script, :ref:`pypeit_obslog`, which provides a simple listing of the available data files; however, use of this script is optional in terms of setup for reducing your data. +.. _setup-file-searching: + +Raw File Searches +================= + +PypeIt scripts that search for raw files in a given directory base the search on +a list of file extensions. These are generally ``.fits`` and ``.fits.gz``, but +some spectrographs specify a different set. + +Some scripts allow you to specify the extension to use for the search, which +*must* be one of the allowed extensions for that spectrograph. E.g., +for a spectrograph that allows ``.fits`` and ``.fits.gz`` extension, you can +specify to only look for the ``.fits`` files, but you *cannot* have it look for +``.fits.bz2`` files. If your raw files have extensions that are currently not +allowed by the code, please `Submit an issue`_. + +If you have both compressed and uncompressed files in your directory, the search +function will generally find both. You are strongly encouraged to only include +one version (compressed or uncompressed) of each file in the directory with your +raw data. + .. _setup-metadata: Use of Metadata to Identify Instrument Configurations @@ -168,7 +189,9 @@ to be the same directory that holds the raw data. 1. First Execution ------------------ -We recommend you first execute ``pypeit_setup`` like this:: +We recommend you first execute ``pypeit_setup`` like this: + +.. code-block:: bash pypeit_setup -r path_to_your_raw_data/LB -s keck_lris_blue @@ -187,7 +210,9 @@ This execution of ``pypeit_setup`` searches for all `*.fits` and `*.fits.gz` files with the provided root directory. Generally, the provided path should **not** contain a wild-card and it is best if you provide the *full* path; however, you can search through multiple -directories as follows:: +directories as follows: + +.. code-block:: bash pypeit_setup -r "/Users/xavier/Keck/LRIS/data/2016apr06/Raw/*/LB" -s keck_lris_blue From 6ceec2374a2164bd16cb04fe6f038cf56a3bac54 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Tue, 13 Aug 2024 10:19:55 -0700 Subject: [PATCH 27/35] test fix --- pypeit/pypeitsetup.py | 6 +++++- pypeit/spectrographs/wht_isis.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pypeit/pypeitsetup.py b/pypeit/pypeitsetup.py index 1ca991db7b..20b95b8c03 100644 --- a/pypeit/pypeitsetup.py +++ b/pypeit/pypeitsetup.py @@ -191,7 +191,11 @@ def from_file_root(cls, root, spectrograph, extension=None): # Spectrograph object spec = load_spectrograph(spectrograph).__class__ files = spec.find_raw_files(root, extension=extension) - msgs.info(f'Found {len(files)} {spec.name} raw files.') + nfiles = len(files) + if nfiles == 0: + msgs.error(f'Unable to find any raw files for {spec.name} in {root}!') + else: + msgs.info(f'Found {nfiles} {spec.name} raw files.') return cls.from_rawfiles(files, spectrograph) @classmethod diff --git a/pypeit/spectrographs/wht_isis.py b/pypeit/spectrographs/wht_isis.py index 38aab5006b..7464e459b8 100644 --- a/pypeit/spectrographs/wht_isis.py +++ b/pypeit/spectrographs/wht_isis.py @@ -125,7 +125,7 @@ class WHTISISBlueSpectrograph(WHTISISSpectrograph): name = 'wht_isis_blue' camera = 'ISISb' comment = 'Blue camera' - allowed_extensions = ['.fit.gz'] + allowed_extensions = ['.fit', '.fit.gz'] def get_detector_par(self, det, hdu=None): """ From 4c322b81c27579902a978b5874cd9567a315fc76 Mon Sep 17 00:00:00 2001 From: rcooke Date: Fri, 16 Aug 2024 13:44:06 +0100 Subject: [PATCH 28/35] update extensions --- pypeit/spectrographs/gemini_gmos.py | 2 ++ pypeit/spectrographs/gemini_gnirs.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pypeit/spectrographs/gemini_gmos.py b/pypeit/spectrographs/gemini_gmos.py index e00506920e..c9ecd8d993 100644 --- a/pypeit/spectrographs/gemini_gmos.py +++ b/pypeit/spectrographs/gemini_gmos.py @@ -108,6 +108,7 @@ class GeminiGMOSSpectrograph(spectrograph.Spectrograph): """ ndet = 3 url = 'http://www.gemini.edu/instrumentation/gmos' + allowed_extensions = ['.fits', '.fits.bz2'] def __init__(self): super().__init__() @@ -1045,6 +1046,7 @@ class GeminiGMOSNSpectrograph(GeminiGMOSSpectrograph): telescope = telescopes.GeminiNTelescopePar() camera = 'GMOS-N' header_name = 'GMOS-N' + allowed_extensions = ['.fits', '.fits.bz2'] class GeminiGMOSNHamSpectrograph(GeminiGMOSNSpectrograph): diff --git a/pypeit/spectrographs/gemini_gnirs.py b/pypeit/spectrographs/gemini_gnirs.py index 989b58a677..52e346661b 100644 --- a/pypeit/spectrographs/gemini_gnirs.py +++ b/pypeit/spectrographs/gemini_gnirs.py @@ -24,6 +24,7 @@ class GeminiGNIRSSpectrograph(spectrograph.Spectrograph): url = 'https://www.gemini.edu/instrumentation/gnirs' header_name = 'GNIRS' telescope = telescopes.GeminiNTelescopePar() + allowed_extensions = ['.fits', '.fits.bz2'] def __init__(self): super().__init__() @@ -587,7 +588,6 @@ class GNIRSIFUSpectrograph(GeminiGNIRSSpectrograph): # * Need to store a wavelength solution for different grating options (Note, the Holy Grail algorithm works pretty well, most of the time) name = 'gemini_gnirs_ifu' pypeline = 'SlicerIFU' - allowed_extensions = ['.fits', '.fits.bz2'] def init_meta(self): super().init_meta() From dd282af727155332655c7117cf72e28354a29211 Mon Sep 17 00:00:00 2001 From: rcooke Date: Sun, 18 Aug 2024 12:51:14 +0100 Subject: [PATCH 29/35] allow fits.gz --- pypeit/spectrographs/gemini_gmos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypeit/spectrographs/gemini_gmos.py b/pypeit/spectrographs/gemini_gmos.py index c9ecd8d993..37616553c7 100644 --- a/pypeit/spectrographs/gemini_gmos.py +++ b/pypeit/spectrographs/gemini_gmos.py @@ -108,7 +108,7 @@ class GeminiGMOSSpectrograph(spectrograph.Spectrograph): """ ndet = 3 url = 'http://www.gemini.edu/instrumentation/gmos' - allowed_extensions = ['.fits', '.fits.bz2'] + allowed_extensions = ['.fits', '.fits.bz2', '.fits.gz'] def __init__(self): super().__init__() @@ -1046,7 +1046,7 @@ class GeminiGMOSNSpectrograph(GeminiGMOSSpectrograph): telescope = telescopes.GeminiNTelescopePar() camera = 'GMOS-N' header_name = 'GMOS-N' - allowed_extensions = ['.fits', '.fits.bz2'] + allowed_extensions = ['.fits', '.fits.bz2', '.fits.gz'] class GeminiGMOSNHamSpectrograph(GeminiGMOSNSpectrograph): From 49d22330fd8e29b9225f87ab7cdf84fb37474918 Mon Sep 17 00:00:00 2001 From: rcooke Date: Tue, 20 Aug 2024 13:14:37 +0100 Subject: [PATCH 30/35] update users Aug 2024 --- presentations/py/users.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presentations/py/users.py b/presentations/py/users.py index 9f3affcddd..73902997e4 100644 --- a/presentations/py/users.py +++ b/presentations/py/users.py @@ -21,9 +21,9 @@ def set_fontsize(ax, fsz): ax.get_xticklabels() + ax.get_yticklabels()): item.set_fontsize(fsz) -user_dates = ["2021-03-11", "2022-04-29", "2022-11-07", "2022-12-06", "2023-06-08", "2023-06-29", "2023-07-11", "2023-09-03", "2023-10-13", "2023-12-01", "2023-12-15", "2024-02-22", "2024-03-21", "2024-04-09", "2024-05-02", "2024-05-19", "2024-06-06", "2024-06-10"] +user_dates = ["2021-03-11", "2022-04-29", "2022-11-07", "2022-12-06", "2023-06-08", "2023-06-29", "2023-07-11", "2023-09-03", "2023-10-13", "2023-12-01", "2023-12-15", "2024-02-22", "2024-03-21", "2024-04-09", "2024-05-02", "2024-05-19", "2024-06-06", "2024-06-10", "2024-08-20"] user_dates = numpy.array([numpy.datetime64(date) for date in user_dates]) -user_number = numpy.array([125, 293, 390, 394, 477, 487, 506, 518, 531, 544, 551, 568, 579, 588, 596, 603, 616, 620]) +user_number = numpy.array([125, 293, 390, 394, 477, 487, 506, 518, 531, 544, 551, 568, 579, 588, 596, 603, 616, 620, 643]) user_pred_dates = numpy.array([numpy.datetime64(date) for date in ["2024-06-10", "2024-12-31", "2025-12-31", "2026-12-31", From 67e4684e0eadd02e6cc41cdd1fc907ec75091b31 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 26 Aug 2024 09:37:21 -0700 Subject: [PATCH 31/35] doc update --- doc/help/pypeit_sensfunc.rst | 16 +++++++++++++--- doc/include/class_datamodel_sensfunc.rst | 1 + doc/include/dependencies_table.rst | 10 +++++----- doc/pypeit_par.rst | 8 +++++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/doc/help/pypeit_sensfunc.rst b/doc/help/pypeit_sensfunc.rst index 8eb7d65e05..701944f327 100644 --- a/doc/help/pypeit_sensfunc.rst +++ b/doc/help/pypeit_sensfunc.rst @@ -1,9 +1,9 @@ .. code-block:: console $ pypeit_sensfunc -h - usage: pypeit_sensfunc [-h] [--algorithm {UVIS,IR}] [--multi MULTI] [-o OUTFILE] - [-s SENS_FILE] [-f FLATFILE] [--debug] - [--par_outfile PAR_OUTFILE] [-v VERBOSITY] + usage: pypeit_sensfunc [-h] [--extr {OPT,BOX}] [--algorithm {UVIS,IR}] + [--multi MULTI] [-o OUTFILE] [-s SENS_FILE] [-f FLATFILE] + [--debug] [--par_outfile PAR_OUTFILE] [-v VERBOSITY] spec1dfile Compute a sensitivity function @@ -14,6 +14,16 @@ options: -h, --help show this help message and exit + --extr {OPT,BOX} Override the default extraction method used for + computing the sensitivity function. Note that it is not + possible to set --extr and simultaneously use a .sens + file with the --sens_file option. If you are using a + .sens file, set the algorithm there via: + + [sensfunc] + extr = BOX + + The extraction options are: OPT or BOX --algorithm {UVIS,IR} Override the default algorithm for computing the sensitivity function. Note that it is not possible to diff --git a/doc/include/class_datamodel_sensfunc.rst b/doc/include/class_datamodel_sensfunc.rst index fbf98d1922..e57591681c 100644 --- a/doc/include/class_datamodel_sensfunc.rst +++ b/doc/include/class_datamodel_sensfunc.rst @@ -8,6 +8,7 @@ Attribute Type Array Type Description ``airmass`` float Airmass of the observation ``algorithm`` str Algorithm used for the sensitivity calculation. ``exptime`` float Exposure time +``extr`` str Extraction method used for the standard star (OPT or BOX) ``pypeline`` str PypeIt pipeline reduction path ``sens`` `astropy.table.table.Table`_ Table with the sensitivity function ``spec1df`` str PypeIt spec1D file used to for sensitivity function diff --git a/doc/include/dependencies_table.rst b/doc/include/dependencies_table.rst index eedeadd17a..bfa5485e86 100644 --- a/doc/include/dependencies_table.rst +++ b/doc/include/dependencies_table.rst @@ -1,5 +1,5 @@ -======================= ========================================================================================================================================================================================================================================================================================================================================================= -Python Version ``>=3.10,<3.13`` -Required for users ``IPython>=7.10.0``, ``PyERFA>=2.0.0``, ``PyYAML>=5.1``, ``astropy>=6.0``, ``bottleneck``, ``configobj>=5.0.6``, ``extension-helpers>=0.1``, ``fast-histogram>=0.11``, ``ginga>=5.1.0``, ``linetools>=0.3.1``, ``matplotlib>=3.7``, ``numpy>=1.23``, ``packaging>=0.19``, ``pygithub``, ``pyqt6``, ``qtpy>=2.0.1``, ``scikit-learn>=1.0``, ``scipy>=1.7`` -Required for developers ``coverage``, ``docutils<0.21``, ``psutil``, ``pygit2``, ``pytest-astropy``, ``pytest-cov``, ``pytest-qt``, ``pytest>=6.0.0``, ``scikit-image``, ``specutils>=1.13``, ``sphinx-automodapi``, ``sphinx>=1.6,<8``, ``sphinx_rtd_theme==2.0.0``, ``tox`` -======================= ========================================================================================================================================================================================================================================================================================================================================================= +======================= ======================================================================================================================================================================================================================================================================================================================================================================= +Python Version ``>=3.10,<3.13`` +Required for users ``IPython>=7.10.0``, ``PyERFA>=2.0.0``, ``PyYAML>=5.1``, ``astropy>=6.0``, ``bottleneck``, ``configobj>=5.0.6``, ``extension-helpers>=0.1``, ``fast-histogram>=0.11``, ``ginga>=5.1.0``, ``linetools>=0.3.1``, ``matplotlib>=3.7``, ``numpy>=1.23,<2.0.0``, ``packaging>=0.19``, ``pygithub``, ``pyqt6<=6.7.0``, ``qtpy>=2.0.1``, ``scikit-learn>=1.0``, ``scipy>=1.7`` +Required for developers ``coverage``, ``docutils<0.21``, ``psutil``, ``pygit2``, ``pytest-astropy``, ``pytest-cov``, ``pytest-qt``, ``pytest>=6.0.0``, ``scikit-image``, ``specutils>=1.13``, ``sphinx-automodapi``, ``sphinx>=1.6,<8``, ``sphinx_rtd_theme==2.0.0``, ``tox`` +======================= ======================================================================================================================================================================================================================================================================================================================================================================= diff --git a/doc/pypeit_par.rst b/doc/pypeit_par.rst index d8cc23ea2c..2f87cf025a 100644 --- a/doc/pypeit_par.rst +++ b/doc/pypeit_par.rst @@ -781,8 +781,9 @@ Key Type Options Default Description ``skip_second_find`` bool .. False Only perform one round of object finding (mainly for quick_look) ``skip_skysub`` bool .. False If True, do not sky subtract when performing object finding. This should be set to True for example when running on data that is already sky-subtracted. Note that for near-IR difference imaging one still wants to remove sky-residuals via sky-subtraction, and so this is typically set to False ``snr_thresh`` int, float .. 10.0 S/N threshold for object finding in wavelength direction smashed image. -``std_spec1d`` str .. .. A PypeIt spec1d file of a previously reduced standard star. The trace of the standard star spectrum is used as a crutch for tracing the object spectra, when a direct trace is not possible (i.e., faint sources). If provided, this overrides use of any standards included in your pypeit file; the standard exposures will still be reduced. +``std_spec1d`` str .. .. A PypeIt spec1d file of a previously reduced standard star. This can be used to trace the object spectra, but the ``use_std_trace`` parameter must be set to True. If provided, this overrides use of any standards included in your pypeit file; the standard exposures will still be reduced. ``trace_npoly`` int .. 5 Order of legendre polynomial fits to object traces. +``use_std_trace`` bool .. True If True, the trace of the standard star spectrum is used as a crutch for tracing the object spectra. This is useful when a direct trace is not possible (i.e., faint sources). Note that a standard star exposure must be included in your pypeit file, or the ``std_spec1d`` parameter must be set for this to work. =========================== ========== ======= ======= ============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================= @@ -939,6 +940,7 @@ Key Type Options ``IR`` :class:`~pypeit.par.pypeitpar.TelluricPar` .. `TelluricPar Keywords`_ Parameters for the IR sensfunc algorithm ``UVIS`` :class:`~pypeit.par.pypeitpar.SensfuncUVISPar` .. `SensfuncUVISPar Keywords`_ Parameters for the UVIS sensfunc algorithm ``algorithm`` str ``UVIS``, ``IR`` ``UVIS`` Specify the algorithm for computing the sensitivity function. The options are: (1) UVIS = Should be used for data with :math:`\lambda < 7000` A. No detailed model of telluric absorption but corrects for atmospheric extinction. (2) IR = Should be used for data with :math:`\lambda > 7000` A. Peforms joint fit for sensitivity function and telluric absorption using HITRAN models. +``extr`` str .. ``OPT`` Extraction method to use for the sensitivity function. Options are: 'OPT' (optimal extraction), 'BOX' (boxcar extraction). Default is 'OPT'. ``extrap_blu`` float .. 0.1 Fraction of minimum wavelength coverage to grow the wavelength coverage of the sensitivitity function in the blue direction (`i.e.`, if the standard star spectrum cuts off at ``wave_min``) the sensfunc will be extrapolated to cover down to (1.0 - ``extrap_blu``) * ``wave_min`` ``extrap_red`` float .. 0.1 Fraction of maximum wavelength coverage to grow the wavelength coverage of the sensitivitity function in the red direction (`i.e.`, if the standard star spectrumcuts off at ``wave_max``) the sensfunc will be extrapolated to cover up to (1.0 + ``extrap_red``) * ``wave_max`` ``flatfile`` str .. .. Flat field file to be used if the sensitivity function model will utilize the blaze function computed from a flat field file in the Calibrations directory, e.g.Calibrations/Flat_A_0_DET01.fits @@ -3027,6 +3029,8 @@ Alterations to the default parameters are: [reduce] [[findobj]] find_trim_edge = 3, 3, + maxnumber_sci = 2 + maxnumber_std = 1 [[skysub]] global_sky_std = False [[extraction]] @@ -4064,6 +4068,8 @@ Alterations to the default parameters are: noise_floor = 0.01 use_illumflat = False [reduce] + [[findobj]] + maxnumber_std = 1 [[skysub]] bspline_spacing = 0.8 [[extraction]] From 7bb82ea056c9a7007c6fa9f2e4ae2c036be46952 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 26 Aug 2024 18:33:05 +0100 Subject: [PATCH 32/35] updated change log for KCWI --- doc/releases/1.16.1dev.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index 0976c9d9fd..f15bd47b5d 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -26,8 +26,11 @@ Functionality/Performance Improvements and Additions Instrument-specific Updates --------------------------- -- Added support for the (decommissioned) AAT/UHRF instrument +- Added support for the (decommissioned) AAT/UHRF instrument +- Updated the requirements of a spectral flip for KCWI (blue) data. If all amplifiers are + used, the data will be flipped. If all amplifiers are used, the data will not be flipped. + Otherwise, the data will be flipped. - Updated X-Shooter detector gain and read noise to come from header, and updated plate scales to the most recent values from the manual. Detailed changes are: From 7e672af506d505aa148fdc4276977fed7bde429f Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 26 Aug 2024 20:08:03 +0100 Subject: [PATCH 33/35] add test for mask around peaks --- pypeit/tests/test_arc.py | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pypeit/tests/test_arc.py b/pypeit/tests/test_arc.py index fef470534e..a112f30e4d 100644 --- a/pypeit/tests/test_arc.py +++ b/pypeit/tests/test_arc.py @@ -2,10 +2,12 @@ Module to run tests on ararclines """ import pytest +import numpy as np from pypeit.core import arc from pypeit import io + def test_detect_lines(): # Using Paranal night sky as an 'arc' arx_sky = io.load_sky_spectrum('paranal_sky.fits') @@ -13,5 +15,45 @@ def test_detect_lines(): = arc.detect_lines(arx_sky.flux.value) assert (len(arx_w) > 3275) + +def test_mask_around_peaks(): + # Generate a fake spectrum + np.random.seed(0) + npks = 5 # Number of peaks to generate + npix = 20 # Number of pixels in each segment + sigma = 2.0 # Fluctuations + linewid = 2.0 # Width of the peaks + noiselev = [np.random.normal(0.0, sigma, npix) for i in range(npks+1)] + ampl = np.random.randint(100*sigma, 200*sigma, npks) + spec = np.array([]) + outbpm = np.array([], dtype=bool) + for i in range(npks): + spec = np.append(spec, noiselev[i]) + outbpm = np.append(outbpm, np.zeros(npix, dtype=bool)) + gauss = ampl[i]*np.exp(-0.5*(np.arange(npix)-npix/2)**2/linewid**2) + spec = np.append(spec, np.random.normal(gauss, sigma)) + if i == 0 or i == 1: + tmpbpm = np.array(2*[False] + 16*[True] + 2*[False]) + elif i == 2: + tmpbpm = np.array(1*[False] + 18*[True] + 1*[False]) + elif i == 3: + tmpbpm = np.array(3*[False] + 15*[True] + 2*[False]) + elif i == 4: + tmpbpm = np.array(20*[True]) + else: + assert (False, "Input test data have changed") + outbpm = np.append(outbpm, tmpbpm.copy()) + outbpm = np.append(outbpm, np.zeros(npix, dtype=bool)) + spec = np.append(spec, noiselev[npks]) + inbpm = np.zeros(len(spec), dtype=bool) + # This is the expected bpm + bpm = arc.mask_around_peaks(spec, inbpm=inbpm) + # Check that all peaks were identified and masked + ind = arc.detect_peaks(bpm) + assert (len(ind) == npks) + # Check the BPM matches exactly + assert (np.array_equal(bpm, outbpm)) + + # Many more functions in pypeit.core.arc that need tests! From 884af8ff2be5053ec7ba0e906bd225545a7f0df8 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 26 Aug 2024 20:19:45 +0100 Subject: [PATCH 34/35] revert to old masking --- deprecated/arc_old.py | 50 +++++++++++++++++++++++++++++++++ pypeit/core/arc.py | 51 ---------------------------------- pypeit/core/findobj_skymask.py | 10 +------ pypeit/tests/test_arc.py | 40 -------------------------- 4 files changed, 51 insertions(+), 100 deletions(-) diff --git a/deprecated/arc_old.py b/deprecated/arc_old.py index edecb94dd2..79b58ded49 100644 --- a/deprecated/arc_old.py +++ b/deprecated/arc_old.py @@ -855,3 +855,53 @@ def saturation_mask(a, satlevel): return mask.astype(int) +def mask_around_peaks(spec, inbpm): + """ + Find peaks in the input spectrum and mask pixels around them. + + All pixels to the left and right of a peak is masked until + a pixel has a lower value than the adjacent pixel. At this + point, we assume that spec has reached the noise level. + + Parameters + ---------- + spec: `numpy.ndarray`_ + Spectrum (1D array) in counts + inbpm: `numpy.ndarray`_ + Input bad pixel mask + + Returns + ------- + outbpm: `numpy.ndarray`_ + Bad pixel mask with pixels around peaks masked + """ + # Find the peak locations + pks = detect_peaks(spec) + + # Initialise some useful variables and the output bpm + xarray = np.arange(spec.size) + specdiff = np.append(np.diff(spec), 0.0) + outbpm = inbpm.copy() + + # Loop over the peaks and mask pixels around them + for i in range(len(pks)): + # Find all pixels to the left of the peak that are above the noise level + wl = np.where((xarray <= pks[i]) & (specdiff > 0.0))[0] + ww = (pks[i]-wl)[::-1] + # Find the first pixel to the left of the peak that is below the noise level + nmask = np.where(np.diff(ww) > 1)[0] + if nmask.size != 0 and nmask[0] > 5: + # Mask all pixels to the left of the peak + mini = max(0,wl.size-nmask[0]-1) + outbpm[wl[mini]:pks[i]] = True + # Find all pixels to the right of the peak that are above the noise level + ww = np.where((xarray >= pks[i]) & (specdiff < 0.0))[0] + # Find the first pixel to the right of the peak that is below the noise level + nmask = np.where(np.diff(ww) > 1)[0] + if nmask.size != 0 and nmask[0] > 5: + # Mask all pixels to the right of the peak + maxi = min(nmask[0], ww.size) + outbpm[pks[i]:ww[maxi]+2] = True + # Return the output bpm + return outbpm + diff --git a/pypeit/core/arc.py b/pypeit/core/arc.py index ca2df6ad71..e41fc7fc8b 100644 --- a/pypeit/core/arc.py +++ b/pypeit/core/arc.py @@ -1070,57 +1070,6 @@ def detect_lines(censpec, sigdetect=5.0, fwhm=4.0, fit_frac_fwhm=1.25, input_thr return tampl_true, tampl, tcent, twid, centerr, ww, arc, nsig -def mask_around_peaks(spec, inbpm): - """ - Find peaks in the input spectrum and mask pixels around them. - - All pixels to the left and right of a peak is masked until - a pixel has a lower value than the adjacent pixel. At this - point, we assume that spec has reached the noise level. - - Parameters - ---------- - spec: `numpy.ndarray`_ - Spectrum (1D array) in counts - inbpm: `numpy.ndarray`_ - Input bad pixel mask - - Returns - ------- - outbpm: `numpy.ndarray`_ - Bad pixel mask with pixels around peaks masked - """ - # Find the peak locations - pks = detect_peaks(spec) - - # Initialise some useful variables and the output bpm - xarray = np.arange(spec.size) - specdiff = np.append(np.diff(spec), 0.0) - outbpm = inbpm.copy() - - # Loop over the peaks and mask pixels around them - for i in range(len(pks)): - # Find all pixels to the left of the peak that are above the noise level - wl = np.where((xarray <= pks[i]) & (specdiff > 0.0))[0] - ww = (pks[i]-wl)[::-1] - # Find the first pixel to the left of the peak that is below the noise level - nmask = np.where(np.diff(ww) > 1)[0] - if nmask.size != 0 and nmask[0] > 5: - # Mask all pixels to the left of the peak - mini = max(0,wl.size-nmask[0]-1) - outbpm[wl[mini]:pks[i]] = True - # Find all pixels to the right of the peak that are above the noise level - ww = np.where((xarray >= pks[i]) & (specdiff < 0.0))[0] - # Find the first pixel to the right of the peak that is below the noise level - nmask = np.where(np.diff(ww) > 1)[0] - if nmask.size != 0 and nmask[0] > 5: - # Mask all pixels to the right of the peak - maxi = min(nmask[0], ww.size) - outbpm[pks[i]:ww[maxi]+2] = True - # Return the output bpm - return outbpm - - def fit_arcspec(xarray, yarray, pixt, fitp): """ Fit a series of pre-identified arc spectrum lines. diff --git a/pypeit/core/findobj_skymask.py b/pypeit/core/findobj_skymask.py index e100df877e..6e4698c844 100644 --- a/pypeit/core/findobj_skymask.py +++ b/pypeit/core/findobj_skymask.py @@ -1763,16 +1763,8 @@ def objs_in_slit(image, ivar, thismask, slit_left, slit_righ, gpm_smash = npix_smash > 0.3*nsmash flux_sum_smash = np.sum((image_rect*gpm_sigclip)[find_min_max_out[0]:find_min_max_out[1]], axis=0) flux_smash = flux_sum_smash*gpm_smash/(npix_smash + (npix_smash == 0.0)) - # Mask around the peaks - peak_bpm = arc.mask_around_peaks(flux_smash, np.logical_not(gpm_smash)) - # Check that the peak mask is not empty - if np.sum(np.logical_not(peak_bpm))/peak_bpm.size < 0.05: # 95% masked! - msgs.warn('Peak masking was too aggressive. Attempting to sigma clip.') - smash_mask = np.logical_not(gpm_smash) - else: - smash_mask = np.logical_not(gpm_smash) | peak_bpm flux_smash_mean, flux_smash_med, flux_smash_std = astropy.stats.sigma_clipped_stats( - flux_smash, mask=smash_mask, sigma_lower=3.0, sigma_upper=3.0) + flux_smash, mask=np.logical_not(gpm_smash), sigma_lower=3.0, sigma_upper=3.0) flux_smash_recen = flux_smash - flux_smash_med # Return if none found and no hand extraction diff --git a/pypeit/tests/test_arc.py b/pypeit/tests/test_arc.py index a112f30e4d..3cde322d37 100644 --- a/pypeit/tests/test_arc.py +++ b/pypeit/tests/test_arc.py @@ -15,45 +15,5 @@ def test_detect_lines(): = arc.detect_lines(arx_sky.flux.value) assert (len(arx_w) > 3275) - -def test_mask_around_peaks(): - # Generate a fake spectrum - np.random.seed(0) - npks = 5 # Number of peaks to generate - npix = 20 # Number of pixels in each segment - sigma = 2.0 # Fluctuations - linewid = 2.0 # Width of the peaks - noiselev = [np.random.normal(0.0, sigma, npix) for i in range(npks+1)] - ampl = np.random.randint(100*sigma, 200*sigma, npks) - spec = np.array([]) - outbpm = np.array([], dtype=bool) - for i in range(npks): - spec = np.append(spec, noiselev[i]) - outbpm = np.append(outbpm, np.zeros(npix, dtype=bool)) - gauss = ampl[i]*np.exp(-0.5*(np.arange(npix)-npix/2)**2/linewid**2) - spec = np.append(spec, np.random.normal(gauss, sigma)) - if i == 0 or i == 1: - tmpbpm = np.array(2*[False] + 16*[True] + 2*[False]) - elif i == 2: - tmpbpm = np.array(1*[False] + 18*[True] + 1*[False]) - elif i == 3: - tmpbpm = np.array(3*[False] + 15*[True] + 2*[False]) - elif i == 4: - tmpbpm = np.array(20*[True]) - else: - assert (False, "Input test data have changed") - outbpm = np.append(outbpm, tmpbpm.copy()) - outbpm = np.append(outbpm, np.zeros(npix, dtype=bool)) - spec = np.append(spec, noiselev[npks]) - inbpm = np.zeros(len(spec), dtype=bool) - # This is the expected bpm - bpm = arc.mask_around_peaks(spec, inbpm=inbpm) - # Check that all peaks were identified and masked - ind = arc.detect_peaks(bpm) - assert (len(ind) == npks) - # Check the BPM matches exactly - assert (np.array_equal(bpm, outbpm)) - - # Many more functions in pypeit.core.arc that need tests! From a9e5cd7c45cc31068a1f8ec7b5b4fe9c286f0914 Mon Sep 17 00:00:00 2001 From: rcooke Date: Mon, 26 Aug 2024 20:22:39 +0100 Subject: [PATCH 35/35] rm old arc line --- .../arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits | Bin 23040 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits diff --git a/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits b/pypeit/data/arc_lines/reid_arxiv/aat_uhrf_UFC27405.fits deleted file mode 100644 index c82c34012c16a73218412b69fa056bd081a8a791..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23040 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 T?FqDhe*PJOe@5W{wGsGVWg76Q