Skip to content
Draft
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
1 change: 1 addition & 0 deletions scopesim/effects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .spectral_trace_list import *
from .spectral_efficiency import *
from .metis_lms_trace_list import *
from .micado_ifu_trace_list import *
from .mosaic_trace_list import *
from .surface_list import *
from .ter_curves import *
Expand Down
7 changes: 7 additions & 0 deletions scopesim/effects/apertures.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FovVolumeList):
logger.debug("Executing %s, FoV setup", self.meta['name'])

x = quantity_from_table("x", self.table,
u.arcsec).to_value(u.arcsec)
y = quantity_from_table("y", self.table,
Expand All @@ -129,6 +130,12 @@ def apply_to(self, obj, **kwargs):
vol["meta"]["xi_min"] = min(x) * u.arcsec
vol["meta"]["xi_max"] = max(x) * u.arcsec

if "offset_type" in self.meta:
vol["meta"]["offset_type"] = self.meta["offset_type"]
vol["meta"]["offset_x"] = self.meta["offset_x"]
vol["meta"]["offset_y"] = self.meta["offset_y"]
else:
vol["meta"]["offset_type"] = "none"
return obj

# Outdated. Remove when removing all old FOVManager code from effects
Expand Down
173 changes: 89 additions & 84 deletions scopesim/effects/metis_lms_trace_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,93 +53,98 @@ def __init__(self, **kwargs):
self.slicelist["top"].max() -
self.slicelist["bottom"].min()])

def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FovVolumeList):
# Create a single volume that covers the aperture and
# the maximum wavelength range of LMS
volumes = [spectral_trace.fov_grid()
for spectral_trace in self.spectral_traces.values()]

wave_min = min(vol["wave_min"] for vol in volumes)
wave_max = max(vol["wave_max"] for vol in volumes)
extracted_vols = obj.extract(axes=["wave"],
edges=([[wave_min, wave_max]]))
obj.volumes = extracted_vols

if isinstance(obj, FieldOfView):
# Application to field of view
logger.debug("Executing %s, FoV", self.meta['name'])
if obj.hdu is not None and obj.hdu.header["NAXIS"] == 3:
obj.cube = obj.hdu
elif obj.hdu is None and obj.cube is None:
obj.cube = obj.make_hdu()

fovcube = obj.cube.data
n_z, n_y, n_x = fovcube.shape
fovwcs = WCS(obj.cube.header)
# Make this linear to avoid jump at RA 0 deg
fovwcs.wcs.ctype = ["LINEAR", "LINEAR", fovwcs.wcs.ctype[2]]
fovwcs_spat = fovwcs.sub(2)
ny_slice = self.meta["slice_samples"]

# Spatial pixel coordinates
xslice, yslice = np.meshgrid(np.arange(n_x),
np.arange(ny_slice))

fovimage = np.zeros((obj.detector_header["NAXIS2"],
obj.detector_header["NAXIS1"]),
dtype=np.float32)

for sptid, spt in tqdm(self.spectral_traces.items(),
desc=" Spectral Traces", position=2):
ymin = spt.meta["fov"]["y_min"]
ymax = spt.meta["fov"]["y_max"]

slicewcs = fovwcs.deepcopy()

slicewcs.wcs.ctype = ["LINEAR", "LINEAR",
slicewcs.wcs.ctype[2]]
slicewcs.wcs.crpix[1] = (ny_slice + 1) / 2
slicewcs.wcs.crval[1] = (ymin + ymax) / 2 / 3600
slicewcs.wcs.cdelt[1] = (ymax - ymin) / ny_slice / 3600
slicewcs_spat = slicewcs.sub(2)

# World coordinates for the slice
xworld, yworld = slicewcs_spat.all_pix2world(xslice,
yslice, 0)
# FOV pixel coordinates for the slice
xfov, yfov = fovwcs_spat.all_world2pix(xworld, yworld, 0)

slicecube = np.zeros((n_z, ny_slice, n_x))
for islice in range(n_z):
ifov = RectBivariateSpline(np.arange(n_y),
np.arange(n_x),
fovcube[islice], kx=1, ky=1)
slicecube[islice] = ifov(yfov, xfov, grid=False)

slicefov = FieldOfView3D(obj.header,
[obj.meta["wave_min"],
obj.meta["wave_max"]])
slicefov.detector_header = obj.detector_header
slicefov.meta["xi_min"] = obj.meta["xi_min"]
slicefov.meta["xi_max"] = obj.meta["xi_max"]
slicefov.meta["trace_id"] = sptid
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)
if slicefov.hdu is not None:
sxmin = slicefov.hdu.header["XMIN"]
sxmax = slicefov.hdu.header["XMAX"]
symin = slicefov.hdu.header["YMIN"]
symax = slicefov.hdu.header["YMAX"]
fovimage[symin:symax, sxmin:sxmax] += slicefov.hdu.data

obj.hdu = fits.ImageHDU(data=fovimage, header=obj.detector_header)
# Overrides for the two apply_to() methods
def apply_to_fovvolumelist(self, obj):
"""Setup

Create a single volume that covers the aperture and
the maximum wavelength range of LMS.
"""
logger.debug("Executing %s: Setup", self.meta['name'])
volumes = [spectral_trace.fov_grid()
for spectral_trace in self.spectral_traces.values()]

wave_min = min(vol["wave_min"] for vol in volumes)
wave_max = max(vol["wave_max"] for vol in volumes)
extracted_vols = obj.extract(axes=["wave"],
edges=([[wave_min, wave_max]]))
obj.volumes = extracted_vols
return obj

def apply_to_fov(self, obj):
"""Application to field of view"""

logger.debug("Executing %s, FoV", self.meta['name'])
if obj.hdu is not None and obj.hdu.header["NAXIS"] == 3:
obj.cube = obj.hdu
elif obj.hdu is None and obj.cube is None:
obj.cube = obj.make_hdu()

fovcube = obj.cube.data
n_z, n_y, n_x = fovcube.shape
fovwcs = WCS(obj.cube.header)
# Make this linear to avoid jump at RA 0 deg
fovwcs.wcs.ctype = ["LINEAR", "LINEAR", fovwcs.wcs.ctype[2]]
fovwcs_spat = fovwcs.sub(2)
ny_slice = self.meta["slice_samples"]

# Spatial pixel coordinates
xslice, yslice = np.meshgrid(np.arange(n_x),
np.arange(ny_slice))

fovimage = np.zeros((obj.detector_header["NAXIS2"],
obj.detector_header["NAXIS1"]),
dtype=np.float32)

for sptid, spt in tqdm(self.spectral_traces.items(),
desc=" Spectral Traces", position=2):
ymin = spt.meta["fov"]["y_min"]
ymax = spt.meta["fov"]["y_max"]

slicewcs = fovwcs.deepcopy()

slicewcs.wcs.ctype = ["LINEAR", "LINEAR",
slicewcs.wcs.ctype[2]]
slicewcs.wcs.crpix[1] = (ny_slice + 1) / 2
slicewcs.wcs.crval[1] = (ymin + ymax) / 2 / 3600
slicewcs.wcs.cdelt[1] = (ymax - ymin) / ny_slice / 3600
slicewcs_spat = slicewcs.sub(2)

# World coordinates for the slice
xworld, yworld = slicewcs_spat.all_pix2world(xslice,
yslice, 0)
# FOV pixel coordinates for the slice
xfov, yfov = fovwcs_spat.all_world2pix(xworld, yworld, 0)

slicecube = np.zeros((n_z, ny_slice, n_x))
for islice in range(n_z):
ifov = RectBivariateSpline(np.arange(n_y),
np.arange(n_x),
fovcube[islice], kx=1, ky=1)
slicecube[islice] = ifov(yfov, xfov, grid=False)

slicefov = FieldOfView3D(obj.header,
[obj.meta["wave_min"],
obj.meta["wave_max"]])
slicefov.detector_header = obj.detector_header
slicefov.meta["xi_min"] = obj.meta["xi_min"]
slicefov.meta["xi_max"] = obj.meta["xi_max"]
slicefov.meta["trace_id"] = sptid
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)
if slicefov.hdu is not None:
sxmin = slicefov.hdu.header["XMIN"]
sxmax = slicefov.hdu.header["XMAX"]
symin = slicefov.hdu.header["YMIN"]
symax = slicefov.hdu.header["YMAX"]
fovimage[symin:symax, sxmin:sxmax] += slicefov.hdu.data

obj.hdu = fits.ImageHDU(data=fovimage, header=obj.detector_header)
return obj


def make_spectral_traces(self):
"""Compute the transformations by interpolation."""
# nslice = len(self._file["Aperture List"].data)
Expand Down
Loading
Loading