From 214446b8fb8c644ee20bd5f3b673977570950c4a Mon Sep 17 00:00:00 2001 From: teutoburg Date: Mon, 25 Mar 2024 16:50:57 +0100 Subject: [PATCH 1/5] Make sure spec ref ID is always an int I recently got an error from an ID that was 1.0 (float). Not sure where it came from, but this will catch it. --- scopesim/optics/fov.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scopesim/optics/fov.py b/scopesim/optics/fov.py index 2d50aa8d..30efcc96 100644 --- a/scopesim/optics/fov.py +++ b/scopesim/optics/fov.py @@ -144,8 +144,9 @@ def extract_from(self, src): spec_refs.add(ref) waves = volume["waves"] * u.Unit(volume["wave_unit"]) - spectra = {ref: fu.extract_range_from_spectrum(src.spectra[ref], waves) - for ref in spec_refs} + spectra = {ref: fu.extract_range_from_spectrum( + src.spectra[int(ref)], waves) + for ref in spec_refs} self.fields = fields_in_fov self.spectra = spectra From e6dd25ce7bd7e31a302bf4b60137ab8058f3391c Mon Sep 17 00:00:00 2001 From: teutoburg Date: Mon, 25 Mar 2024 16:51:56 +0100 Subject: [PATCH 2/5] Use exceptions instead of return None --- scopesim/effects/metis_lms_trace_list.py | 23 +++++++---- scopesim/effects/spectral_trace_list_utils.py | 41 +++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/scopesim/effects/metis_lms_trace_list.py b/scopesim/effects/metis_lms_trace_list.py index cde712a0..9f0fe3ec 100644 --- a/scopesim/effects/metis_lms_trace_list.py +++ b/scopesim/effects/metis_lms_trace_list.py @@ -13,9 +13,9 @@ from ..utils import from_currsys, find_file, quantify, get_logger from .spectral_trace_list import SpectralTraceList -from .spectral_trace_list_utils import SpectralTrace -from .spectral_trace_list_utils import Transform2D -from .spectral_trace_list_utils import make_image_interpolations +from .spectral_trace_list_utils import (SpectralTrace, Transform2D, + make_image_interpolations, + SpecTraceError) from .apertures import ApertureMask from .ter_curves import TERCurve from ..base_classes import FieldOfViewBase, FOVSetupBase @@ -138,7 +138,11 @@ def apply_to(self, obj, **kwargs): slicefov.cube = fits.ImageHDU(header=slicewcs.to_header(), data=slicecube) # slicefov.cube.writeto(f"slicefov_{sptid}.fits", overwrite=True) - slicefov.hdu = spt.map_spectra_to_focal_plane(slicefov) + try: + slicefov.hdu = spt.map_spectra_to_focal_plane(slicefov) + except SpecTraceError as err: + logger.warning(err) + continue sxmin = slicefov.hdu.header["XMIN"] sxmax = slicefov.hdu.header["XMAX"] @@ -223,10 +227,13 @@ def rectify_cube(self, hdulist, xi_min=None, xi_max=None, interps=None, for i, spt in enumerate(self.spectral_traces.values()): spt.wave_min = wave_min spt.wave_max = wave_max - result = spt.rectify(hdulist, interps=interps, - wave_min=wave_min, wave_max=wave_max, - xi_min=xi_min, xi_max=xi_max, - bin_width=dwave) + try: + result = spt.rectify(hdulist, interps=interps, + wave_min=wave_min, wave_max=wave_max, + xi_min=xi_min, xi_max=xi_max, + bin_width=dwave) + except SpecTraceError as err: + logger.warning(err) cube[:, i, :] = result.data.T # FIXME: use wcs object here diff --git a/scopesim/effects/spectral_trace_list_utils.py b/scopesim/effects/spectral_trace_list_utils.py index 849887b1..f93f8081 100644 --- a/scopesim/effects/spectral_trace_list_utils.py +++ b/scopesim/effects/spectral_trace_list_utils.py @@ -30,6 +30,26 @@ logger = get_logger(__name__) +class SpecTraceError(Exception): + """Base class for exceptions in this module.""" + + +class NoXlimError(SpecTraceError): + """Dunno.""" + + +class TraceOutsideFovError(SpecTraceError): + """The spectral trace falls outside the given FOV.""" + + +class OutsideFilterRangeError(SpecTraceError): + """Trace wavelength is not within filter waverange.""" + + +class KwNotFoundError(SpecTraceError): + """Required keyword for rectification was not found.""" + + class SpectralTrace: """Definition of one spectral trace. @@ -168,8 +188,7 @@ def map_spectra_to_focal_plane(self, fov): xi_min=xi_min, xi_max=xi_max) if xlim_mm is None: - logger.warning("xlim_mm is None") - return None + raise NoXlimError("xlim_mm is None") fov_header = fov.header det_header = fov.detector_header @@ -190,9 +209,8 @@ def map_spectra_to_focal_plane(self, fov): # Check if spectral trace footprint is outside FoV if xmax < 0 or xmin > naxis1d or ymax < 0 or ymin > naxis2d: - logger.info( - "Spectral trace %d: footprint is outside FoV", fov.trace_id) - return None + raise TraceOutsideFovError( + f"Spectral trace {fov.trace_id}: footprint is outside FoV") # Only work on parts within the FoV xmin = max(xmin, 0) @@ -222,7 +240,7 @@ def map_spectra_to_focal_plane(self, fov): xilam = XiLamImage(fov, self.dlam_per_pix) self._xilamimg = xilam # ..todo: remove or make available with a debug flag? except ValueError: - logger.warning(" ---> %d gave ValueError", self.trace_id) + logger.warning(" ---> %s gave ValueError", self.trace_id) npix_xi, npix_lam = xilam.npix_xi, xilam.npix_lam xilam_wcs = xilam.wcs @@ -323,8 +341,8 @@ def rectify(self, hdulist, interps=None, wcs=None, **kwargs): wave_max = kwargs.get("wave_max", self.wave_max) if wave_max < self.wave_min or wave_min > self.wave_max: - logger.info(" Outside filter range") - return None + raise OutsideFilterRangeError(" Outside filter range") + wave_min = max(wave_min, self.wave_min) wave_max = min(wave_max, self.wave_max) logger.info(" %.02f .. %.02f um", wave_min, wave_max) @@ -345,15 +363,14 @@ def rectify(self, hdulist, interps=None, wcs=None, **kwargs): try: xi_min = hdulist[0].header["HIERARCH INS SLIT XIMIN"] except KeyError: - logger.error("xi_min not found") - return None + raise KwNotFoundError("xi_min not found") + xi_max = kwargs.get("xi_max", None) if xi_max is None: try: xi_max = hdulist[0].header["HIERARCH INS SLIT XIMAX"] except KeyError: - logger.error("xi_max not found") - return None + raise KwNotFoundError("xi_max not found") if wcs is None: wcs = WCS(naxis=2) From a1475b73dfcd8134eae86036593c75356722256a Mon Sep 17 00:00:00 2001 From: teutoburg Date: Mon, 25 Mar 2024 16:52:18 +0100 Subject: [PATCH 3/5] Formatting and unused import --- scopesim/effects/metis_lms_trace_list.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scopesim/effects/metis_lms_trace_list.py b/scopesim/effects/metis_lms_trace_list.py index 9f0fe3ec..edc7c4d4 100644 --- a/scopesim/effects/metis_lms_trace_list.py +++ b/scopesim/effects/metis_lms_trace_list.py @@ -1,5 +1,5 @@ """SpectralTraceList and SpectralTrace for the METIS LM spectrograph.""" -import copy + import warnings import numpy as np @@ -163,11 +163,12 @@ def make_spectral_traces(self): self.meta["angle"] = tempres["Angle"] spec_traces = {} - for sli in np.arange(self.meta["nslice"]): - slicename = "Slice " + str(sli + 1) + for sli in range(self.meta["nslice"]): + slicename = f"Slice {sli + 1}" spec_traces[slicename] = MetisLMSSpectralTrace( self._file, - spslice=sli, params=self.meta) + spslice=sli, + params=self.meta) self.spectral_traces = spec_traces @@ -287,7 +288,7 @@ def __init__(self, hdulist, spslice, params, **kwargs): super().__init__(polyhdu, **params) self._file = hdulist - self.meta["description"] = "Slice " + str(spslice + 1) + self.meta["description"] = f"Slice {spslice + 1}" self.meta["trace_id"] = f"Slice {spslice + 1}" self.meta.update(params) # Provisional: From d44ed392569c10d2fdfbda16540c366a916ccc85 Mon Sep 17 00:00:00 2001 From: teutoburg Date: Mon, 25 Mar 2024 16:52:41 +0100 Subject: [PATCH 4/5] Fix unresolved bang string in filename --- scopesim/effects/metis_lms_trace_list.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/scopesim/effects/metis_lms_trace_list.py b/scopesim/effects/metis_lms_trace_list.py index edc7c4d4..c3963860 100644 --- a/scopesim/effects/metis_lms_trace_list.py +++ b/scopesim/effects/metis_lms_trace_list.py @@ -315,8 +315,7 @@ def fov_grid(self): y_min = aperture["bottom"] y_max = aperture["top"] - filename_det_layout = from_currsys("!DET.layout.file_name", cmds=self.cmds) - layout = ioascii.read(find_file(filename_det_layout)) + layout = ioascii.read(find_file(self.cmds["!DET.layout.filename"])) det_lims = {} xhw = layout["pixel_size"] * layout["x_size"] / 2 yhw = layout["pixel_size"] * layout["y_size"] / 2 @@ -570,13 +569,10 @@ class MetisLMSEfficiency(TERCurve): } def __init__(self, **kwargs): - # TODO: Refactor these _class_params? - self.meta = copy.copy(self._class_params) - assert "grat_spacing" in self.meta, "grat_spacing is missing from self.meta 1" - super().__init__(**kwargs) - assert "grat_spacing" in self.meta, "grat_spacing is missing from self.meta 2" + self.meta = self._class_params + self.meta.update(kwargs) - filename = find_file(self.meta["filename"]) + filename = find_file(from_currsys(self.meta["filename"], kwargs.get("cmds"))) wcal = fits.getdata(filename, extname="WCAL") if "wavelen" in kwargs: wavelen = from_currsys(kwargs["wavelen"], kwargs.get("cmds")) From cdd1a54aa0175ad14e56c0880fb6d11fbf2a862d Mon Sep 17 00:00:00 2001 From: teutoburg Date: Mon, 25 Mar 2024 17:01:07 +0100 Subject: [PATCH 5/5] Fix duplicate keyword --- scopesim/effects/metis_lms_trace_list.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scopesim/effects/metis_lms_trace_list.py b/scopesim/effects/metis_lms_trace_list.py index c3963860..8b616b94 100644 --- a/scopesim/effects/metis_lms_trace_list.py +++ b/scopesim/effects/metis_lms_trace_list.py @@ -584,6 +584,13 @@ def __init__(self, **kwargs): lam, efficiency = self.make_ter_curve(wcal, wavelen) + # HACK: Somehow we end up with duplicate keywords here. This hack + # should not be necessary at all! Investigate what's really + # going on... + self.meta.pop("wavelength", None) + self.meta.pop("transmission", None) + self.meta.pop("emissivity", None) + super().__init__(wavelength=lam, transmission=efficiency, emissivity=np.zeros_like(lam),