From 674d19ec12759cfc94204057de0194702c369729 Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Fri, 23 Aug 2024 17:56:54 -1000 Subject: [PATCH 1/5] script added --- pypeit/scripts/__init__.py | 1 + pypeit/scripts/chk_flexure.py | 110 ++++++++++++++++++++++++++++++++++ setup.cfg | 1 + 3 files changed, 112 insertions(+) create mode 100644 pypeit/scripts/chk_flexure.py diff --git a/pypeit/scripts/__init__.py b/pypeit/scripts/__init__.py index ff0164f966..b16da7c36e 100644 --- a/pypeit/scripts/__init__.py +++ b/pypeit/scripts/__init__.py @@ -9,6 +9,7 @@ from pypeit.scripts import chk_alignments from pypeit.scripts import chk_edges from pypeit.scripts import chk_flats +from pypeit.scripts import chk_flexure from pypeit.scripts import chk_tilts from pypeit.scripts import chk_for_calibs from pypeit.scripts import chk_noise_1dspec diff --git a/pypeit/scripts/chk_flexure.py b/pypeit/scripts/chk_flexure.py new file mode 100644 index 0000000000..e7a44686fb --- /dev/null +++ b/pypeit/scripts/chk_flexure.py @@ -0,0 +1,110 @@ +""" +This script displays the flexure (spatial or spectral) applied to the science data. + +.. include common links, assuming primary doc root is up one directory +.. include:: ../include/links.rst +""" + +from pypeit.scripts import scriptbase + + +class ChkFlexure(scriptbase.ScriptBase): + + @classmethod + def get_parser(cls, width=None): + parser = super().get_parser(description='Print QA on flexure to the screen', + width=width) + + parser.add_argument('input_file', type=str, nargs='+', help='One or more PypeIt spec2d or spec1d file') + inp = parser.add_mutually_exclusive_group(required=True) + inp.add_argument('--spec', default=False, action='store_true', help='Check the spectral flexure') + inp.add_argument('--spat', default=False, action='store_true', help='Check the spatial flexure') + # parser.add_argument('type', type=str, + # help='Type of flexure to check. Options are: spat, spec') + parser.add_argument('--try_old', default=False, action='store_true', + help='Attempt to load old datamodel versions. A crash may ensue..') + return parser + + @staticmethod + def main(args): + + from IPython import embed + import numpy as np + from astropy.io import fits + from astropy.table import Table + from pypeit import spec2dobj, specobjs, msgs + + chk_version = not args.try_old + + # tables to return + return_tables = [] + + # Loop over the input files + for in_file in args.input_file: + + print(f'\nCheck fluxure for file: {in_file}') + + # What kind of file are we?? + hdul = fits.open(in_file) + head0 = hdul[0].header + file_type = None + if 'PYP_CLS' in head0.keys() and head0['PYP_CLS'].strip() == 'AllSpec2DObj': + file_type = 'AllSpec2D' + elif 'DMODCLS' in head0.keys() and head0['DMODCLS'].strip() == 'SpecObjs': + file_type = 'SpecObjs' + else: + msgs.error("Bad file type input!") + + if file_type == 'AllSpec2D': + # load the spec2d file + allspec2D = spec2dobj.AllSpec2DObj.from_fits(in_file, chk_version=chk_version) + # Loop on Detectors + for det in allspec2D.detectors: + print('') + print('='*50 + f'{det:^7}' + '='*51) + # get and print the spectral flexure + if args.spec: + spec_flex = allspec2D[det].sci_spec_flexure + spec_flex.rename_column('sci_spec_flexure', 'global_spec_shift') + if np.all(spec_flex['global_spec_shift'] != None): + spec_flex['global_spec_shift'].format = '0.3f' + # print the table + spec_flex.pprint_all() + # return the table + return_tables.append(spec_flex) + # get and print the spatial flexure + if args.spat: + spat_flex = allspec2D[det].sci_spat_flexure + # print the value + print(f'Spat shift: {spat_flex}') + # return the value + return_tables.append(spat_flex) + elif file_type == 'SpecObjs': + # no spat flexure in spec1d file + if args.spat: + msgs.error("Spat flexure not available in the spec1d file, try with a spec2d file") + # load the spec1d file + sobjs = specobjs.SpecObjs.from_fitsfile(in_file, chk_version=chk_version) + spec_flex = Table() + spec_flex['NAME'] = sobjs.NAME + spec_flex['global_spec_shift'] = sobjs.FLEX_SHIFT_GLOBAL + if np.all(spec_flex['global_spec_shift'] != None): + spec_flex['global_spec_shift'].format = '0.3f' + spec_flex['local_spec_shift'] = sobjs.FLEX_SHIFT_LOCAL + if np.all(spec_flex['local_spec_shift'] != None): + spec_flex['local_spec_shift'].format = '0.3f' + spec_flex['total_spec_shift'] = sobjs.FLEX_SHIFT_TOTAL + if np.all(spec_flex['total_spec_shift'] != None): + spec_flex['total_spec_shift'].format = '0.3f' + # print the table + spec_flex.pprint_all() + # return the table + return_tables.append(spec_flex) + + return return_tables + + + + + + diff --git a/setup.cfg b/setup.cfg index 0f8d481f3a..7228205d96 100644 --- a/setup.cfg +++ b/setup.cfg @@ -110,6 +110,7 @@ console_scripts = pypeit_arxiv_solution = pypeit.scripts.arxiv_solution:ArxivSolution.entry_point pypeit_cache_github_data = pypeit.scripts.cache_github_data:CacheGithubData.entry_point pypeit_clean_cache = pypeit.scripts.clean_cache:CleanCache.entry_point + pypeit_chk_flexure = pypeit.scripts.chk_flexure:ChkFlexure.entry_point pypeit_chk_for_calibs = pypeit.scripts.chk_for_calibs:ChkForCalibs.entry_point pypeit_chk_noise_1dspec = pypeit.scripts.chk_noise_1dspec:ChkNoise1D.entry_point pypeit_chk_noise_2dspec = pypeit.scripts.chk_noise_2dspec:ChkNoise2D.entry_point From d60f96785d9df14d77558d1c37b939f6605e2f8f Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Fri, 23 Aug 2024 17:57:49 -1000 Subject: [PATCH 2/5] remove commented out --- pypeit/scripts/chk_flexure.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pypeit/scripts/chk_flexure.py b/pypeit/scripts/chk_flexure.py index e7a44686fb..d9548cbb83 100644 --- a/pypeit/scripts/chk_flexure.py +++ b/pypeit/scripts/chk_flexure.py @@ -19,8 +19,6 @@ def get_parser(cls, width=None): inp = parser.add_mutually_exclusive_group(required=True) inp.add_argument('--spec', default=False, action='store_true', help='Check the spectral flexure') inp.add_argument('--spat', default=False, action='store_true', help='Check the spatial flexure') - # parser.add_argument('type', type=str, - # help='Type of flexure to check. Options are: spat, spec') parser.add_argument('--try_old', default=False, action='store_true', help='Attempt to load old datamodel versions. A crash may ensue..') return parser From ed3c09742cd64f5fc1807c3a4d4ab54506b09646 Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Mon, 26 Aug 2024 10:34:40 -1000 Subject: [PATCH 3/5] added doc to release --- doc/releases/1.16.1dev.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index 4c00f878a2..59f48520e2 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -60,6 +60,8 @@ Script Changes - Added the ``--extr`` parameter in the ``pypeit_sensfunc`` script (also as a SensFuncPar) to allow the user to specify the extraction method to use when computing the sensitivity function (before only optimal extraction was used). +- Added ``pypeit_chk_flexure`` script to check both spatial and spectral flexure applied to + the reduced data. Datamodel Changes ----------------- From 6a0367efe32e87aa2dfa2fd52a5638ef4e3f8b54 Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Mon, 26 Aug 2024 10:49:28 -1000 Subject: [PATCH 4/5] small change --- pypeit/scripts/chk_flexure.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pypeit/scripts/chk_flexure.py b/pypeit/scripts/chk_flexure.py index d9548cbb83..027acd3d27 100644 --- a/pypeit/scripts/chk_flexure.py +++ b/pypeit/scripts/chk_flexure.py @@ -40,7 +40,7 @@ def main(args): # Loop over the input files for in_file in args.input_file: - print(f'\nCheck fluxure for file: {in_file}') + msgs.info(f'Checking fluxure for file: {in_file}') # What kind of file are we?? hdul = fits.open(in_file) @@ -98,7 +98,9 @@ def main(args): spec_flex.pprint_all() # return the table return_tables.append(spec_flex) - + + # space between files for clarity + print('') return return_tables From 2388003aee48b2f6d2bb5724727c376204386a7d Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Mon, 26 Aug 2024 13:16:06 -1000 Subject: [PATCH 5/5] move to a function --- pypeit/core/flexure.py | 77 ++++++++++++++++++++++++++++++++++- pypeit/scripts/chk_flexure.py | 63 ++++------------------------ 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/pypeit/core/flexure.py b/pypeit/core/flexure.py index 02265a3426..a36e581ec4 100644 --- a/pypeit/core/flexure.py +++ b/pypeit/core/flexure.py @@ -17,6 +17,7 @@ from astropy import stats from astropy import units from astropy.io import ascii +from astropy.table import Table import scipy.signal import scipy.optimize as opt from scipy import interpolate @@ -36,7 +37,7 @@ from pypeit.datamodel import DataContainer from pypeit.images.detector_container import DetectorContainer from pypeit.images.mosaic import Mosaic -from pypeit import specobj, specobjs +from pypeit import specobj, specobjs, spec2dobj from pypeit import wavemodel from IPython import embed @@ -1394,6 +1395,80 @@ def sky_em_residuals(wave:np.ndarray, flux:np.ndarray, return dwave[m], diff[m], diff_err[m], los[m], los_err[m] +def flexure_diagnostic(file, file_type='spec2d', flexure_type='spec', chk_version=False): + """ + Print the spectral or spatial flexure of a spec2d or spec1d file + Args: + file (:obj:`str`, `Path`_): + Filename of the spec2d or spec1d file to check + file_type (:obj:`str`, optional): + Type of the file to check. Options are 'spec2d' or 'spec1d'. Default is 'spec2d'. + flexure_type (:obj:`str`, optional): + Type of flexure to check. Options are 'spec' or 'spat'. Default is 'spec'. + chk_version (:obj:`bool`, optional): + If True, raise an error if the datamodel version or type check failed. + If False, throw a warning only. Default is False. + + Returns: + :obj:`astropy.table.Table` or :obj:`float`: + - If file_type is 'spec2d' and flexure_type is 'spec', return a table with the spectral flexure + - If file_type is 'spec2d' and flexure_type is 'spat', return the spatial flexure + - If file_type is 'spec1d', return a table with the spectral flexure + + """ + + # value to return + return_flex = None + + if file_type == 'spec2d': + # load the spec2d file + allspec2D = spec2dobj.AllSpec2DObj.from_fits(file, chk_version=chk_version) + # Loop on Detectors + for det in allspec2D.detectors: + print('') + print('=' * 50 + f'{det:^7}' + '=' * 51) + # get and print the spectral flexure + if flexure_type == 'spec': + spec_flex = allspec2D[det].sci_spec_flexure + spec_flex.rename_column('sci_spec_flexure', 'global_spec_shift') + if np.all(spec_flex['global_spec_shift'] != None): + spec_flex['global_spec_shift'].format = '0.3f' + # print the table + spec_flex.pprint_all() + # return the table + return_flex = spec_flex + # get and print the spatial flexure + if flexure_type == 'spat': + spat_flex = allspec2D[det].sci_spat_flexure + # print the value + print(f'Spat shift: {spat_flex}') + # return the value + return_flex = spat_flex + elif file_type == 'spec1d': + # no spat flexure in spec1d file + if flexure_type == 'spat': + msgs.error("Spat flexure not available in the spec1d file, try with a spec2d file") + # load the spec1d file + sobjs = specobjs.SpecObjs.from_fitsfile(file, chk_version=chk_version) + spec_flex = Table() + spec_flex['NAME'] = sobjs.NAME + spec_flex['global_spec_shift'] = sobjs.FLEX_SHIFT_GLOBAL + if np.all(spec_flex['global_spec_shift'] != None): + spec_flex['global_spec_shift'].format = '0.3f' + spec_flex['local_spec_shift'] = sobjs.FLEX_SHIFT_LOCAL + if np.all(spec_flex['local_spec_shift'] != None): + spec_flex['local_spec_shift'].format = '0.3f' + spec_flex['total_spec_shift'] = sobjs.FLEX_SHIFT_TOTAL + if np.all(spec_flex['total_spec_shift'] != None): + spec_flex['total_spec_shift'].format = '0.3f' + # print the table + spec_flex.pprint_all() + # return the table + return_flex = spec_flex + + return return_flex + + # TODO -- Consider separating the methods from the DataContainer as per calibrations class MultiSlitFlexure(DataContainer): """ diff --git a/pypeit/scripts/chk_flexure.py b/pypeit/scripts/chk_flexure.py index 027acd3d27..d384dc8e29 100644 --- a/pypeit/scripts/chk_flexure.py +++ b/pypeit/scripts/chk_flexure.py @@ -27,16 +27,12 @@ def get_parser(cls, width=None): def main(args): from IPython import embed - import numpy as np from astropy.io import fits - from astropy.table import Table - from pypeit import spec2dobj, specobjs, msgs + from pypeit import msgs + from pypeit.core import flexure chk_version = not args.try_old - # tables to return - return_tables = [] - # Loop over the input files for in_file in args.input_file: @@ -47,61 +43,18 @@ def main(args): head0 = hdul[0].header file_type = None if 'PYP_CLS' in head0.keys() and head0['PYP_CLS'].strip() == 'AllSpec2DObj': - file_type = 'AllSpec2D' + file_type = 'spec2d' elif 'DMODCLS' in head0.keys() and head0['DMODCLS'].strip() == 'SpecObjs': - file_type = 'SpecObjs' + file_type = 'spec1d' else: msgs.error("Bad file type input!") - if file_type == 'AllSpec2D': - # load the spec2d file - allspec2D = spec2dobj.AllSpec2DObj.from_fits(in_file, chk_version=chk_version) - # Loop on Detectors - for det in allspec2D.detectors: - print('') - print('='*50 + f'{det:^7}' + '='*51) - # get and print the spectral flexure - if args.spec: - spec_flex = allspec2D[det].sci_spec_flexure - spec_flex.rename_column('sci_spec_flexure', 'global_spec_shift') - if np.all(spec_flex['global_spec_shift'] != None): - spec_flex['global_spec_shift'].format = '0.3f' - # print the table - spec_flex.pprint_all() - # return the table - return_tables.append(spec_flex) - # get and print the spatial flexure - if args.spat: - spat_flex = allspec2D[det].sci_spat_flexure - # print the value - print(f'Spat shift: {spat_flex}') - # return the value - return_tables.append(spat_flex) - elif file_type == 'SpecObjs': - # no spat flexure in spec1d file - if args.spat: - msgs.error("Spat flexure not available in the spec1d file, try with a spec2d file") - # load the spec1d file - sobjs = specobjs.SpecObjs.from_fitsfile(in_file, chk_version=chk_version) - spec_flex = Table() - spec_flex['NAME'] = sobjs.NAME - spec_flex['global_spec_shift'] = sobjs.FLEX_SHIFT_GLOBAL - if np.all(spec_flex['global_spec_shift'] != None): - spec_flex['global_spec_shift'].format = '0.3f' - spec_flex['local_spec_shift'] = sobjs.FLEX_SHIFT_LOCAL - if np.all(spec_flex['local_spec_shift'] != None): - spec_flex['local_spec_shift'].format = '0.3f' - spec_flex['total_spec_shift'] = sobjs.FLEX_SHIFT_TOTAL - if np.all(spec_flex['total_spec_shift'] != None): - spec_flex['total_spec_shift'].format = '0.3f' - # print the table - spec_flex.pprint_all() - # return the table - return_tables.append(spec_flex) - + # Check the flexure + flexure.flexure_diagnostic(in_file, file_type=file_type, flexure_type='spat' if args.spat else 'spec', + chk_version=chk_version) + # space between files for clarity print('') - return return_tables