From 1bbeebeca168a805c3750556ef35e6eb3db8bf4e Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 13:33:26 +0200 Subject: [PATCH 01/22] propagate ncoeff to ech_findobj_ineach_order --- pypeit/core/findobj_skymask.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pypeit/core/findobj_skymask.py b/pypeit/core/findobj_skymask.py index fe56f70bc4..d0c518bd3a 100644 --- a/pypeit/core/findobj_skymask.py +++ b/pypeit/core/findobj_skymask.py @@ -1265,6 +1265,7 @@ def ech_objfind(image, ivar, slitmask, slit_left, slit_righ, slit_spat_id, order det=det, inmask=inmask, std_trace=std_trace, + ncoeff=ncoeff, specobj_dict=specobj_dict, snr_thresh=snr_thresh, show_peaks=show_peaks, From 3305c3855bf1c390f1b67c1a649887ea7a0c9afc Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 13:33:56 +0200 Subject: [PATCH 02/22] updated xshooter detector parameters --- pypeit/spectrographs/vlt_xshooter.py | 94 +++++++--------------------- 1 file changed, 21 insertions(+), 73 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index b12ac92cbb..e86ca9c904 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -230,21 +230,15 @@ def get_detector_par(self, det, hdu=None): specaxis = 1, specflip = False, spatflip = False, - platescale = 0.197, # average between order 11 & 30, see manual - darkcurr = 0.0, # e-/pixel/hour + platescale = 0.245, # average across all orders, see manual + darkcurr = 72.0, # e-/pixel/hour saturation = 2.0e5, # I think saturation may never be a problem here since there are many DITs nonlinear = 0.86, mincounts = -1e10, numamplifiers = 1, - gain = np.atleast_1d(2.12), # - ronoise = np.atleast_1d(8.0), # ?? more precise value? #TODO the read noise is exposure time dependent and should be grabbed from header + gain = np.atleast_1d(2.29), + ronoise = np.atleast_1d(8.0), # Read noise depends on exposure time (see XShooter manual) but this is the typical value. datasec = np.atleast_1d('[4:2044,4:]'), # These are all unbinned pixels - # EMA: No real overscan for XSHOOTER-NIR: - # See Table 6 in http://www.eso.org/sci/facilities/paranal/instruments/xshooter/doc/VLT-MAN-ESO-14650-4942_P103v1.pdf - # The overscan region below contains only zeros - # ToDo should we just set it as empty? - # JXP says yes - #oscansec = np.atleast_1d('[4:2044,1:3]'), # These are all unbinned pixels. ) return detector_container.DetectorContainer(**detector_dict) @@ -263,19 +257,12 @@ def default_pypeit_par(cls): turn_off = dict(use_illumflat=False, use_biasimage=False, use_overscan=False, use_darkimage=False) par.reset_all_processimages_par(**turn_off) - # Require dark images to be subtracted from the flat images used for - # tracing, pixelflats, and illumflats - # par['calibrations']['traceframe']['process']['use_darkimage'] = True - # par['calibrations']['pixelflatframe']['process']['use_darkimage'] = True - # par['calibrations']['illumflatframe']['process']['use_darkimage'] = True - # TODO: `mask_cr` now defaults to True for darks. Should this be turned off? # Is this needed below? par['scienceframe']['process']['sigclip'] = 20.0 par['scienceframe']['process']['satpix'] = 'nothing' # TODO tune up LA COSMICS parameters here for X-shooter as tellurics are being excessively masked - # Adjustments to slit and tilts for NIR par['calibrations']['slitedges']['edge_thresh'] = 50. par['calibrations']['slitedges']['fit_order'] = 8 @@ -304,7 +291,6 @@ def default_pypeit_par(cls): par['calibrations']['wavelengths']['reid_arxiv'] = 'vlt_xshooter_nir.fits' par['calibrations']['wavelengths']['cc_thresh'] = 0.50 par['calibrations']['wavelengths']['cc_local_thresh'] = 0.50 -# par['calibrations']['wavelengths']['ech_fix_format'] = True # Echelle parameters par['calibrations']['wavelengths']['echelle'] = True par['calibrations']['wavelengths']['ech_nspec_coeff'] = 5 @@ -313,7 +299,6 @@ def default_pypeit_par(cls): par['calibrations']['wavelengths']['qa_log'] = False # Flats - #par['calibrations']['standardframe']['process']['illumflatten'] = False par['calibrations']['flatfield']['tweak_slits_thresh'] = 0.90 par['calibrations']['flatfield']['tweak_slits_maxfrac'] = 0.10 @@ -324,23 +309,11 @@ def default_pypeit_par(cls): par['reduce']['skysub']['bspline_spacing'] = 0.8 par['reduce']['skysub']['global_sky_std'] = False # Do not perform global sky subtraction for standard stars par['reduce']['extraction']['model_full_slit'] = True # local sky subtraction operates on entire slit - par['reduce']['findobj']['trace_npoly'] = 8 + par['reduce']['findobj']['find_extrap_npoly'] = 3 + par['reduce']['findobj']['trace_npoly'] = 3 par['reduce']['findobj']['maxnumber_sci'] = 2 # Assume that there is only one object on the slit. par['reduce']['findobj']['maxnumber_std'] = 1 # Assume that there is only one object on the slit. - - # The settings below enable X-shooter dark subtraction from the traceframe and pixelflatframe, but enforce - # that this bias won't be subtracted from other images. It is a hack for now, because eventually we want to - # perform this operation with the dark frame class, and we want to attach individual sets of darks to specific - # images. - #par['calibrations']['biasframe']['useframe'] = 'bias' - #par['calibrations']['traceframe']['process']['bias'] = 'force' - #par['calibrations']['pixelflatframe']['process']['bias'] = 'force' - #par['calibrations']['arcframe']['process']['bias'] = 'skip' - #par['calibrations']['tiltframe']['process']['bias'] = 'skip' - #par['calibrations']['standardframe']['process']['bias'] = 'skip' - #par['scienceframe']['process']['bias'] = 'skip' - # Sensitivity function parameters par['sensfunc']['algorithm'] = 'IR' par['sensfunc']['polyorder'] = 8 @@ -488,32 +461,6 @@ def bpm(self, filename, det, shape=None, msbias=None): vlt_sc = dataPaths.static_calibs / 'vlt_xshoooter' bpm_loc = np.loadtxt(vlt_sc.get_file_path('BP_MAP_RP_NIR.dat'), usecols=(0,1)) bpm_img[bpm_loc[:,0].astype(int),bpm_loc[:,1].astype(int)] = 1. -# try : -# bpm_loc = np.loadtxt(vlt_sc.get_file_path('BP_MAP_RP_NIR.dat'), usecols=(0,1)) -# except IOError : -# # TODO: Do we need this anymore? Both the *.dat and *.fits.gz -# # files are present in the repo. -# msgs.warn('BP_MAP_RP_NIR.dat not present in the static database') -# bpm_fits = io.fits_open(vlt_sc.get_file_path('BP_MAP_RP_NIR.fits.gz')) -# # ToDo: this depends on datasec, biassec, specflip, and specaxis -# # and should become able to adapt to these parameters. -# # Flipping and shifting BPM to match the PypeIt format -# y_shift = -2 -# x_shift = 18 -# bpm_data = np.flipud(bpm_fits[0].data) -# y_len = len(bpm_data[:,0]) -# x_len = len(bpm_data[0,:]) -# bpm_data_pypeit = np.full( ((y_len+abs(y_shift)),(x_len+abs(x_shift))) , 0) -# bpm_data_pypeit[:-abs(y_shift),:-abs(x_shift)] = bpm_data_pypeit[:-abs(y_shift),:-abs(x_shift)] + bpm_data -# bpm_data_pypeit = np.roll(bpm_data_pypeit,-y_shift,axis=0) -# bpm_data_pypeit = np.roll(bpm_data_pypeit,x_shift,axis=1) -# filt_bpm = bpm_data_pypeit[1:y_len,1:x_len]>100. -# y_bpm, x_bpm = np.where(filt_bpm) -# bpm_loc = np.array([y_bpm,x_bpm]).T -# # NOTE: This directly access the path, but we shouldn't be doing that... -# np.savetxt(vlt_sc.path / 'BP_MAP_RP_NIR.dat', bpm_loc, fmt=['%d','%d']) -# finally : -# bpm_img[bpm_loc[:,0].astype(int),bpm_loc[:,1].astype(int)] = 1. return bpm_img @@ -548,8 +495,8 @@ def spec_min_max(self): Return the minimum and maximum spectral pixel expected for the spectral range of each order. """ - spec_max = np.asarray([1467,1502,1540, 1580,1620,1665,1720, 1770,1825,1895, 1966, 2000,2000,2000,2000,2000]) - spec_min = np.asarray([420 ,390 , 370, 345, 315, 285, 248, 210, 165, 115, 63, 10, 0, 0, 0, 0]) + spec_max = np.asarray([1477,1513,1547, 1588,1628,1682,1733, 1795, 1855, 1930, 2005, 2040,2040,2040,2040,2040]) + spec_min = np.asarray([420 ,390 , 370, 345, 315, 285, 248, 210, 165, 115, 58, 5, 0, 0, 0, 0]) return np.vstack((spec_min, spec_max)) def order_platescale(self, order_vec, binning=None): @@ -572,9 +519,10 @@ def order_platescale(self, order_vec, binning=None): # TODO: Either assume a linear trend or measure this # X-shooter manual says, but gives no exact numbers per order. # NIR: 52.4 pixels (0.210"/pix) at order 11 to 59.9 pixels (0.184"/pix) at order 26. - - # Right now I just assume a simple linear trend - plate_scale = 0.184 + (order_vec - 26)*(0.184-0.210)/(26 - 11) + + + # FBD 2024: Latest versions of manual give 0.245" as the average + plate_scale = 0.245*np.ones_like(order_vec) return plate_scale @property @@ -633,17 +581,17 @@ def get_detector_par(self, det, hdu=None): specaxis = 0, specflip = False, spatflip = False, - platescale = 0.16, # average from order 17 and order 30, see manual + platescale = 0.154, # average from order 17 and order 30, see manual darkcurr = 0.0, # e-/pixel/hour saturation = 65535., nonlinear = 0.86, mincounts = -1e10, numamplifiers = 1, - gain = np.atleast_1d(0.595), # FITS format is flipped: PrimaryHDU (2106, 4000) w/respect to Python - ronoise = np.atleast_1d(3.1), # raw unbinned images are (4000,2106) (spec, spat) - datasec=np.atleast_1d('[:,11:2058]'), # pre and oscan are in the spatial direction - oscansec=np.atleast_1d('[:,2059:2106]'), - ) + gain = np.atleast_1d(0.64), # Assumes high gain. TODO: grab this from the header + ronoise = np.atleast_1d(3.4), # Assumes slow readout. TODO: grab this from the header + datasec=np.atleast_1d('[:,11:2058]'), # FITS format is flipped: PrimaryHDU (2106, 4000) w/respect to Python + oscansec=np.atleast_1d('[:,2059:2106]'), # raw unbinned images are (4000,2106) (spec, spat) + ) # pre and oscan are in the spatial direction return detector_container.DetectorContainer(**detector_dict) @classmethod @@ -924,14 +872,14 @@ def get_detector_par(self, det, hdu=None): specaxis = 0, specflip = True, spatflip = True, - platescale = 0.161, # average from order 14 and order 24, see manual + platescale = 0.164, # average from order 14 and order 24, see manual darkcurr = 0.0, # e-/pixel/hour saturation = 65000., nonlinear = 0.86, mincounts = -1e10, numamplifiers = 1, - gain = np.atleast_1d(1.61), - ronoise = np.atleast_1d(2.60), + gain = np.atleast_1d(0.63), # Assumes high gain. TODO: grab this from the header + ronoise = np.atleast_1d(2.4), # Assumes slow readout. TODO: grab this from the header datasec = np.atleast_1d('[:,49:2096]'), # '[49:2000,1:2999]', oscansec = np.atleast_1d('[:,1:48]'), # '[1:48, 1:2999]', ) From ba27a741988045725a74c8a1a2cf24fea5c734d8 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 13:46:43 +0200 Subject: [PATCH 03/22] revert testing pars --- pypeit/spectrographs/vlt_xshooter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index e86ca9c904..98a6628112 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -309,8 +309,7 @@ def default_pypeit_par(cls): par['reduce']['skysub']['bspline_spacing'] = 0.8 par['reduce']['skysub']['global_sky_std'] = False # Do not perform global sky subtraction for standard stars par['reduce']['extraction']['model_full_slit'] = True # local sky subtraction operates on entire slit - par['reduce']['findobj']['find_extrap_npoly'] = 3 - par['reduce']['findobj']['trace_npoly'] = 3 + par['reduce']['findobj']['trace_npoly'] = 8 par['reduce']['findobj']['maxnumber_sci'] = 2 # Assume that there is only one object on the slit. par['reduce']['findobj']['maxnumber_std'] = 1 # Assume that there is only one object on the slit. From ae51a809532646b07b0d61c4711a7e80dee31585 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 13:47:47 +0200 Subject: [PATCH 04/22] cleanup spacing --- pypeit/spectrographs/vlt_xshooter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index 98a6628112..a0a612c484 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -494,8 +494,8 @@ def spec_min_max(self): Return the minimum and maximum spectral pixel expected for the spectral range of each order. """ - spec_max = np.asarray([1477,1513,1547, 1588,1628,1682,1733, 1795, 1855, 1930, 2005, 2040,2040,2040,2040,2040]) - spec_min = np.asarray([420 ,390 , 370, 345, 315, 285, 248, 210, 165, 115, 58, 5, 0, 0, 0, 0]) + spec_max = np.asarray([1477,1513,1547, 1588,1628,1682,1733,1795,1855,1930,2005,2040,2040,2040,2040,2040]) + spec_min = np.asarray([420 ,390 , 370, 345, 315, 285, 248, 210, 165, 115, 58, 5, 0, 0, 0, 0]) return np.vstack((spec_min, spec_max)) def order_platescale(self, order_vec, binning=None): From 6af894fdd6bab5fb1f9a75eac80b2e44019ca2d6 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 13:49:25 +0200 Subject: [PATCH 05/22] cleanup comments --- pypeit/spectrographs/vlt_xshooter.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index a0a612c484..7945edd538 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -515,12 +515,8 @@ def order_platescale(self, order_vec, binning=None): `numpy.ndarray`_: An array with the platescale for each order provided by ``order``. """ - # TODO: Either assume a linear trend or measure this - # X-shooter manual says, but gives no exact numbers per order. - # NIR: 52.4 pixels (0.210"/pix) at order 11 to 59.9 pixels (0.184"/pix) at order 26. - - - # FBD 2024: Latest versions of manual give 0.245" as the average + # TODO: Figure out the order-dependence of the updated plate scale + # From the X-Shooter P113 manual, average over all orders. No order-dependent values given. plate_scale = 0.245*np.ones_like(order_vec) return plate_scale From 450b622bd6b68d5e4c2890b6b0725e07185e0dff Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Fri, 26 Jul 2024 14:14:20 +0200 Subject: [PATCH 06/22] bumped up trace_npoly slightly after dev suite testing --- pypeit/spectrographs/vlt_xshooter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index 7945edd538..b9d7c3f27c 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -309,7 +309,7 @@ def default_pypeit_par(cls): par['reduce']['skysub']['bspline_spacing'] = 0.8 par['reduce']['skysub']['global_sky_std'] = False # Do not perform global sky subtraction for standard stars par['reduce']['extraction']['model_full_slit'] = True # local sky subtraction operates on entire slit - par['reduce']['findobj']['trace_npoly'] = 8 + par['reduce']['findobj']['trace_npoly'] = 10 par['reduce']['findobj']['maxnumber_sci'] = 2 # Assume that there is only one object on the slit. par['reduce']['findobj']['maxnumber_std'] = 1 # Assume that there is only one object on the slit. @@ -416,6 +416,8 @@ def check_frame_type(self, ftype, fitstbl, exprng=None): | (fitstbl['target'] == 'LAMP,FLAT')) & good_dark_seq) + # TODO: Figure out how to identify lampoffflats + if ftype == 'pinhole': # Don't type pinhole return np.zeros(len(fitstbl), dtype=bool) From 5f5cfccaa8d0dd4bd9eafcd34ad31764f8238995 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Tue, 30 Jul 2024 11:45:57 +0200 Subject: [PATCH 07/22] changed default fwhm_fromlines behavior --- pypeit/spectrographs/vlt_xshooter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index b9d7c3f27c..be478f7ecd 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -297,6 +297,9 @@ def default_pypeit_par(cls): par['calibrations']['wavelengths']['ech_norder_coeff'] = 5 par['calibrations']['wavelengths']['ech_sigrej'] = 3.0 par['calibrations']['wavelengths']['qa_log'] = False + # Measured FWHM is correct, but resulting wavelength solution is poor. + # This should be explored further, but for now, turning off fwhm_fromlines helps. + par['calibrations']['wavelengths']['fwhm_fromlines'] = False # Flats par['calibrations']['flatfield']['tweak_slits_thresh'] = 0.90 From 26a1233904115fe5167ecc69be9b5343e550d079 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Tue, 30 Jul 2024 11:59:57 +0200 Subject: [PATCH 08/22] gain and read noise for uvb/vis from headers --- pypeit/spectrographs/vlt_xshooter.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index be478f7ecd..f31ceea7af 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -222,6 +222,7 @@ def get_detector_par(self, det, hdu=None): :class:`~pypeit.images.detector_container.DetectorContainer`: Object with the detector metadata. """ + # Detector 1 detector_dict = dict( binning = '1,1', # No binning in near-IR @@ -572,6 +573,10 @@ def get_detector_par(self, det, hdu=None): # Binning # TODO: Could this be detector dependent?? binning = '1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning') + + # Grab the gain and read noise from the header. + gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( @@ -587,8 +592,8 @@ def get_detector_par(self, det, hdu=None): nonlinear = 0.86, mincounts = -1e10, numamplifiers = 1, - gain = np.atleast_1d(0.64), # Assumes high gain. TODO: grab this from the header - ronoise = np.atleast_1d(3.4), # Assumes slow readout. TODO: grab this from the header + gain = np.atleast_1d(gain), + ronoise = np.atleast_1d(ronoise), datasec=np.atleast_1d('[:,11:2058]'), # FITS format is flipped: PrimaryHDU (2106, 4000) w/respect to Python oscansec=np.atleast_1d('[:,2059:2106]'), # raw unbinned images are (4000,2106) (spec, spat) ) # pre and oscan are in the spatial direction @@ -863,6 +868,10 @@ def get_detector_par(self, det, hdu=None): """ # Binning binning = '1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning') + + # Grab the gain and read noise from the header. + gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( @@ -878,8 +887,8 @@ def get_detector_par(self, det, hdu=None): nonlinear = 0.86, mincounts = -1e10, numamplifiers = 1, - gain = np.atleast_1d(0.63), # Assumes high gain. TODO: grab this from the header - ronoise = np.atleast_1d(2.4), # Assumes slow readout. TODO: grab this from the header + gain = np.atleast_1d(gain), + ronoise = np.atleast_1d(ronoise), datasec = np.atleast_1d('[:,49:2096]'), # '[49:2000,1:2999]', oscansec = np.atleast_1d('[:,1:48]'), # '[1:48, 1:2999]', ) From e0d89a88db59e139cd9ec3fa2fdd62e7bef7a53f Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Tue, 30 Jul 2024 12:10:37 +0200 Subject: [PATCH 09/22] correctly frametype lampoffflats --- pypeit/spectrographs/vlt_xshooter.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index f31ceea7af..05e1a01058 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -413,15 +413,13 @@ def check_frame_type(self, ftype, fitstbl, exprng=None): | (fitstbl['target'] == 'LAMP,FLAT')) & good_flat_seq) - if ftype in ['dark']: + if ftype in ['lampoffflats']: # Lamp off flats are taken second (even exposure number) return good_exp & (((fitstbl['target'] == 'LAMP,DFLAT') | (fitstbl['target'] == 'LAMP,QFLAT') | (fitstbl['target'] == 'LAMP,FLAT')) & good_dark_seq) - # TODO: Figure out how to identify lampoffflats - if ftype == 'pinhole': # Don't type pinhole return np.zeros(len(fitstbl), dtype=bool) From b11a72c7a8a4334cc01d89f622f424689c14f5e4 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Tue, 30 Jul 2024 12:17:46 +0200 Subject: [PATCH 10/22] doc update --- doc/releases/1.16.1dev.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index cf5b4712c0..e08a2ea65d 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -21,6 +21,9 @@ Functionality/Performance Improvements and Additions Instrument-specific Updates --------------------------- +- Updated X-Shooter detector gain and read noise to come from header, and + updated plate scales to the most recent values from the manual. + Script Changes -------------- From 21d2711dfb52a195b225bbc1798a8bd95127a4d3 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 5 Aug 2024 15:15:37 -0700 Subject: [PATCH 11/22] change pyqt6 dependency; limit attempts to start ginga --- pypeit/display/display.py | 7 ++++--- setup.cfg | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pypeit/display/display.py b/pypeit/display/display.py index 2b53dc466f..ab8b29155e 100644 --- a/pypeit/display/display.py +++ b/pypeit/display/display.py @@ -60,7 +60,7 @@ def connect_to_ginga(host='localhost', port=9000, raise_err=False, allow_new=Fal # was just instantiated for a maximum number of iterations. # If the connection is remains unsuccessful, an error is # thrown stating that the connection timed out. - maxiter = int(1e6) + maxiter = int(3e4) for i in range(maxiter): try: viewer = grc.RemoteClient(host, port) @@ -72,8 +72,9 @@ def connect_to_ginga(host='localhost', port=9000, raise_err=False, allow_new=Fal break if i == maxiter-1: msgs.error('Timeout waiting for ginga to start. If window does not appear, type ' - '`ginga --modules=RC,SlitWavelength` on the command line. In either case, wait for ' - 'the ginga viewer to open and try the pypeit command again.') + '`ginga --modules=RC,SlitWavelength` on the command line. In either ' + 'case, wait for the ginga viewer to open and try the pypeit command ' + 'again.') return viewer if raise_err: diff --git a/setup.cfg b/setup.cfg index b8e9ded954..9d3691e1fe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -50,7 +50,7 @@ install_requires = qtpy>=2.0.1 pygithub bottleneck - pyqt6 + pyqt6<=6.7.0 scripts = bin/pypeit_c_enabled bin/pypeit_chk_plugins From 73d062e4df642402b655f5db84b57e3a74aea0da Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 5 Aug 2024 15:25:57 -0700 Subject: [PATCH 12/22] numpy version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9d3691e1fe..f29285fd16 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,7 @@ python_requires = >=3.10,<3.13 setup_requires = setuptools_scm include_package_data = True install_requires = - numpy>=1.23 + numpy<2.0.0 astropy>=6.0 extension-helpers>=0.1 packaging>=0.19 From ef373e46d438892747c894f98683972f4b482adf Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 12 Aug 2024 15:28:40 -0700 Subject: [PATCH 13/22] numpy version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index f29285fd16..1c0ac31359 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,7 @@ python_requires = >=3.10,<3.13 setup_requires = setuptools_scm include_package_data = True install_requires = - numpy<2.0.0 + numpy>=1.23,<2.0.0 astropy>=6.0 extension-helpers>=0.1 packaging>=0.19 From e9c6f8dc9ab0e76822ce6aa21b62820ed6c89776 Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Tue, 13 Aug 2024 16:21:02 -0700 Subject: [PATCH 14/22] detailed changes --- doc/releases/1.16.1dev.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/releases/1.16.1dev.rst b/doc/releases/1.16.1dev.rst index ce89a684d7..4e231e5a4a 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -22,7 +22,16 @@ Instrument-specific Updates --------------------------- - Updated X-Shooter detector gain and read noise to come from header, and - updated plate scales to the most recent values from the manual. + updated plate scales to the most recent values from the manual. Detailed + changes are: + - NIR arm: + - Platescale updated from 0.197 to 0.245 arcsec/pixel + - Dark current updated from 0. to 72. e-/pixel/hr + - Gain updated from 2.12 to 2.29 e-/DN + - VIS arm: + - Platescale updated from an order-dependent value, to being 0.245 + arcsec/pixel for all orders + Script Changes -------------- From ca6a46f5312c623c89a135860c31c70365d4c265 Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Mon, 19 Aug 2024 13:29:09 +0200 Subject: [PATCH 15/22] pr comments on platescale --- pypeit/spectrographs/vlt_xshooter.py | 34 ++++++++++++---------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index 05e1a01058..7dae261c1e 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -573,8 +573,9 @@ def get_detector_par(self, det, hdu=None): binning = '1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning') # Grab the gain and read noise from the header. - gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] - ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] + # If hdu not present, use typical defaults + gain = np.atleast_1d(0.64) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = np.atleast_1d(3.4) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( @@ -759,15 +760,12 @@ def order_platescale(self, order_vec, binning=None): `numpy.ndarray`_: An array with the platescale for each order provided by ``order``. """ - # VIS has no binning, but for an instrument with binning we would do this binspectral, binspatial = parse.parse_binning(binning) - - # ToDO Either assume a linear trend or measure this - # X-shooter manual says, but gives no exact numbers per order. - # VIS: 65.9 pixels (0.167"/pix) at order 17 to 72.0 pixels (0.153"/pix) at order 30. - - # Right now I just assume a simple linear trend - plate_scale = 0.153 + (order_vec - 30)*(0.153-0.167)/(30 - 17) + + # TODO: Figure out the order-dependence of the updated plate scale + # From the X-Shooter P113 manual, average over all orders. No order-dependent values given. + plate_scale = 0.154*np.ones_like(order_vec) + return plate_scale*binspatial @property @@ -868,8 +866,8 @@ def get_detector_par(self, det, hdu=None): binning = '1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning') # Grab the gain and read noise from the header. - gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] - ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] + gain = np.atleast_1d(0.63) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = np.atleast_1d(2.4) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( @@ -1071,15 +1069,11 @@ def order_platescale(self, order_vec, binning = None): """ binspectral, binspatial = parse.parse_binning(binning) - # ToDO Either assume a linear trend or measure this - # X-shooter manual says, but gives no exact numbers per order. - # UVB: 65.9 pixels (0.167“/pix) at order 14 to 70.8 pixels (0.155”/pix) at order 24 - - # Assume a simple linear trend - plate_scale = 0.155 + (order_vec - 24)*(0.155-0.167)/(24 - 14) + # TODO: Figure out the order-dependence of the updated plate scale + # From the X-Shooter P113 manual, average over all orders. No order-dependent values given. + plate_scale = 0.164*np.ones_like(order_vec) - # Right now I just took the average - return np.full(self.norders, 0.161)*binspatial + return plate_scale*binspatial def bpm(self, filename, det, shape=None, msbias=None): """ From 3aac40abf3063c264c3aaaf64909eea3ec07a68b Mon Sep 17 00:00:00 2001 From: Frederick Davies Date: Mon, 19 Aug 2024 13:35:08 +0200 Subject: [PATCH 16/22] oops, did not need to remove these Nones --- pypeit/spectrographs/vlt_xshooter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pypeit/spectrographs/vlt_xshooter.py b/pypeit/spectrographs/vlt_xshooter.py index 7dae261c1e..98b5cf6895 100644 --- a/pypeit/spectrographs/vlt_xshooter.py +++ b/pypeit/spectrographs/vlt_xshooter.py @@ -574,8 +574,8 @@ def get_detector_par(self, det, hdu=None): # Grab the gain and read noise from the header. # If hdu not present, use typical defaults - gain = np.atleast_1d(0.64) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] - ronoise = np.atleast_1d(3.4) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] + gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( @@ -866,8 +866,8 @@ def get_detector_par(self, det, hdu=None): binning = '1,1' if hdu is None else self.get_meta_value(self.get_headarr(hdu), 'binning') # Grab the gain and read noise from the header. - gain = np.atleast_1d(0.63) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] - ronoise = np.atleast_1d(2.4) if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] + gain = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 CONAD'] + ronoise = None if hdu is None else hdu[0].header['HIERARCH ESO DET OUT1 RON'] # Detector 1 detector_dict = dict( From 674d19ec12759cfc94204057de0194702c369729 Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Fri, 23 Aug 2024 17:56:54 -1000 Subject: [PATCH 17/22] 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 18/22] 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 0966f402269c58f8b7e7a61d58ac93fe87d03dbd Mon Sep 17 00:00:00 2001 From: Kyle Westfall Date: Mon, 26 Aug 2024 08:31:34 -0700 Subject: [PATCH 19/22] release update --- 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 d638c3b21e..4c00f878a2 100644 --- a/doc/releases/1.16.1dev.rst +++ b/doc/releases/1.16.1dev.rst @@ -35,7 +35,10 @@ Instrument-specific Updates - Dark current updated from 0. to 72. e-/pixel/hr - Gain updated from 2.12 to 2.29 e-/DN - VIS arm: - - Platescale updated from an order-dependent value, to being 0.245 + - Platescale updated from an order-dependent value, to being 0.154 + arcsec/pixel for all orders + - UVB arm: + - Platescale updated from an order-dependent value, to being 0.164 arcsec/pixel for all orders From ed3c09742cd64f5fc1807c3a4d4ab54506b09646 Mon Sep 17 00:00:00 2001 From: Debora Pelliccia Date: Mon, 26 Aug 2024 10:34:40 -1000 Subject: [PATCH 20/22] 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 21/22] 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 22/22] 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