Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix METIS IFU mode #391

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 32 additions & 21 deletions scopesim/effects/metis_lms_trace_list.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""SpectralTraceList and SpectralTrace for the METIS LM spectrograph."""
import copy

import warnings

import numpy as np
Expand All @@ -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
Expand Down Expand Up @@ -138,7 +138,11 @@
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

Check warning on line 145 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L141-L145

Added lines #L141 - L145 were not covered by tests

sxmin = slicefov.hdu.header["XMIN"]
sxmax = slicefov.hdu.header["XMAX"]
Expand All @@ -159,11 +163,12 @@
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}"

Check warning on line 167 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L166-L167

Added lines #L166 - L167 were not covered by tests
spec_traces[slicename] = MetisLMSSpectralTrace(
self._file,
spslice=sli, params=self.meta)
spslice=sli,
params=self.meta)

self.spectral_traces = spec_traces

Expand Down Expand Up @@ -223,10 +228,13 @@
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,

Check warning on line 232 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L231-L232

Added lines #L231 - L232 were not covered by tests
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)

Check warning on line 237 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L236-L237

Added lines #L236 - L237 were not covered by tests
cube[:, i, :] = result.data.T

# FIXME: use wcs object here
Expand Down Expand Up @@ -280,7 +288,7 @@
super().__init__(polyhdu, **params)

self._file = hdulist
self.meta["description"] = "Slice " + str(spslice + 1)
self.meta["description"] = f"Slice {spslice + 1}"

Check warning on line 291 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L291

Added line #L291 was not covered by tests
self.meta["trace_id"] = f"Slice {spslice + 1}"
self.meta.update(params)
# Provisional:
Expand All @@ -307,8 +315,7 @@
y_min = aperture["bottom"]
y_max = aperture["top"]

filename_det_layout = from_currsys("!DET.layout.file_name", cmds=self.cmds)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah here you introduced the bug that you then fixed in AstarVienna/irdb#165 . We can merge that one if we also merge this one. Let me review the rest of this PR first though

layout = ioascii.read(find_file(filename_det_layout))
layout = ioascii.read(find_file(self.cmds["!DET.layout.filename"]))

Check warning on line 318 in scopesim/effects/metis_lms_trace_list.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_lms_trace_list.py#L318

Added line #L318 was not covered by tests
det_lims = {}
xhw = layout["pixel_size"] * layout["x_size"] / 2
yhw = layout["pixel_size"] * layout["y_size"] / 2
Expand Down Expand Up @@ -562,13 +569,10 @@
}

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)
Comment on lines +572 to +573
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this copy() seems rather dangerous, as now any instance of MetisLMSEfficiency can change the values of other instances. E.g.:

from scopesim.effects.metis_lms_trace_list import MetisLMSEfficiency
eff1 = MetisLMSEfficiency(wavelen=4.2, filename="METIS/TRACE_LMS.fits")
print(f"{eff1.meta['eff_max']=}")
eff2 = MetisLMSEfficiency(wavelen=4.2, filename="METIS/TRACE_LMS.fits", eff_max=42)
print(f"{eff2.meta['eff_max']=}")
print(f"{eff1.meta['eff_max']=}")
eff3 = MetisLMSEfficiency(wavelen=4.2, filename="METIS/TRACE_LMS.fits")
print(f"{eff3.meta['eff_max']=}")

will print

eff1.meta['eff_max']=0.75
eff2.meta['eff_max']=42
eff1.meta['eff_max']=42
eff3.meta['eff_max']=42

is that intentional?


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"))
Expand All @@ -580,6 +584,13 @@

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...
Comment on lines +587 to +589
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe because you removed the copy() in __init__()? You directly set self.meta = self._class_params, which means that all MetisLMSEfficiency instances share the same .meta.

Just guessing. And since I'm already started with 'single comments', I'll keep doing that :-).

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),
Expand Down
41 changes: 29 additions & 12 deletions scopesim/effects/spectral_trace_list_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -168,8 +188,7 @@
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")

Check warning on line 191 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L191

Added line #L191 was not covered by tests

fov_header = fov.header
det_header = fov.detector_header
Expand All @@ -190,9 +209,8 @@

# 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(

Check warning on line 212 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L212

Added line #L212 was not covered by tests
f"Spectral trace {fov.trace_id}: footprint is outside FoV")

# Only work on parts within the FoV
xmin = max(xmin, 0)
Expand Down Expand Up @@ -222,7 +240,7 @@
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)

Check warning on line 243 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L243

Added line #L243 was not covered by tests

npix_xi, npix_lam = xilam.npix_xi, xilam.npix_lam
xilam_wcs = xilam.wcs
Expand Down Expand Up @@ -323,8 +341,8 @@
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")

Check warning on line 344 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L344

Added line #L344 was not covered by tests

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)
Expand All @@ -345,15 +363,14 @@
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")

Check warning on line 366 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L366

Added line #L366 was not covered by tests

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")

Check warning on line 373 in scopesim/effects/spectral_trace_list_utils.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/spectral_trace_list_utils.py#L373

Added line #L373 was not covered by tests

if wcs is None:
wcs = WCS(naxis=2)
Expand Down
5 changes: 3 additions & 2 deletions scopesim/optics/fov.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading