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

METIS WCU effects #494

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
05411f8
start with BlackBodySource
oczoske Nov 5, 2024
5fed12a
reinstate utils.seq, with tests
oczoske Nov 6, 2024
3c2fc2d
add emission to BlackBodySource
oczoske Nov 6, 2024
fb84570
update test, add more
oczoske Nov 6, 2024
0f5337d
debug messages
oczoske Nov 12, 2024
3495999
Merge branch 'main' into oc/metis_wcu
oczoske Nov 12, 2024
af05978
One more debug message
oczoske Nov 13, 2024
8171ac9
Hack to let NAXIS=3 wcses pass
oczoske Nov 14, 2024
e5e3379
BlackBodySource interface with tests
oczoske Nov 14, 2024
c46081b
allow int; do not allow negative temp
oczoske Nov 14, 2024
f0f2239
test for emission v temperature
oczoske Nov 15, 2024
1425562
shorter
oczoske Nov 15, 2024
237c727
Merge main
oczoske Nov 18, 2024
eb4e0ad
integrating sphere output intensity
oczoske Nov 19, 2024
de97413
correction to background intensity
oczoske Nov 19, 2024
c392f59
First attempt to make FP mask
oczoske Nov 20, 2024
5b81a24
make background_source a list - needed for METIS_WCU
oczoske Nov 21, 2024
0dca38a
add config_file
oczoske Nov 22, 2024
a1480fa
consistency between two definitions of background source
oczoske Nov 24, 2024
17d0e8c
clean up pixarea multiplication
oczoske Nov 24, 2024
5c0a141
user config file; apply pinhole size
oczoske Nov 25, 2024
4725735
PupilMaskWheel
oczoske Nov 25, 2024
5a729fe
start laser lamp
oczoske Nov 26, 2024
65ad6f4
Update tests
oczoske Dec 5, 2024
6c68867
fix tests
oczoske Dec 13, 2024
723e48c
one more test for lss
oczoske Dec 13, 2024
aaf544e
clean up
oczoske Dec 19, 2024
4d27c49
Merge branch 'main' into oc/metis_wcu
oczoske Dec 19, 2024
8f401b5
Add second laser
oczoske Jan 7, 2025
1e4740a
tunable laser
oczoske Jan 8, 2025
5cd1cbe
Start FPMask class
oczoske Jan 9, 2025
7ddeb45
Complete fpmask; instantiation in metis_wcu still open
oczoske Jan 10, 2025
1eb6bba
Find mask definition files
oczoske Jan 13, 2025
552243e
reject holes outside of field
oczoske Jan 14, 2025
8624664
do not check against pre-installed masks
oczoske Jan 14, 2025
8588b3c
flux-controlling aperture
oczoske Jan 14, 2025
1b97d52
Put bb_aperture in the right place
oczoske Jan 15, 2025
01a6e90
test for bb_aperture
oczoske Jan 15, 2025
c66a8a6
appease pylint in test
oczoske Jan 17, 2025
7d5be2a
remove debug action
oczoske Jan 17, 2025
f093d48
TEL.area now set to 1 by default
oczoske Jan 17, 2025
cc4f167
let find_file not raise an error
oczoske Jan 17, 2025
c3faa7f
revert previous commit, protect test otherwise
oczoske Jan 17, 2025
3097763
Move FPMask around
oczoske Jan 17, 2025
f105ae1
pinholes placed to subpixel accuracy
oczoske Jan 24, 2025
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
2 changes: 2 additions & 0 deletions scopesim/effects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@

from .rotation import *

from .metis_wcu import *

# from . import effects_utils
2 changes: 2 additions & 0 deletions scopesim/effects/apertures.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ def __init__(self, **kwargs):
def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FOVSetupBase):
logger.debug("Executing %s, FoV setup", self.meta['name'])
x = quantity_from_table("x", self.table,
u.arcsec).to(u.arcsec).value
y = quantity_from_table("y", self.table,
Expand Down Expand Up @@ -298,6 +299,7 @@ def __init__(self, **kwargs):
def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FOVSetupBase):
logger.debug("Executing %s, FoV setup", self.meta['name'])
new_vols = []
for row in self.table:
vols = obj.extract(["x", "y"], ([row["left"], row["right"]],
Expand Down
15 changes: 15 additions & 0 deletions scopesim/effects/metis_wcu/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
"""
Effects for METIS Warm Calibration Unit

Classes:
-
-
"""

from ...utils import get_logger

logger = get_logger(__name__)

from .metis_wcu import WCUSource
from .fpmask import FPMask
125 changes: 125 additions & 0 deletions scopesim/effects/metis_wcu/fpmask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
"""A class for the METIS WCU focal-plane mask"""

from pathlib import Path
import numpy as np
from matplotlib import pyplot as plt
from astropy.io import fits
from astropy import units as u
from ..data_container import DataContainer
from ...utils import find_file, from_currsys, get_logger
from ...optics.image_plane_utils import sub_pixel_fractions

logger = get_logger(__name__)

class FPMask:
"""Focal-plane mask for the METIS WCU

Parameters
----------
See :class:`DataContainer` for input parameters

"""
hdr = {"BG_SRC": True,
"BG_SURF": "WCU focal plane mask", # TODO more specific?
"CTYPE1": "LINEAR",
"CTYPE2": "LINEAR",
"CRPIX1": 1024.5,
"CRPIX2": 1024.5,
"CRVAL1": 0.,
"CRVAL2": 0.,
"CUNIT1": "arcsec",
"CUNIT2": "arcsec",
"CDELT1": 0.00547,
"CDELT2": 0.00547,
"BUNIT": "PHOTLAM arcsec-2",
"SOLIDANG": "arcsec-2"}

def __init__(self,
maskname: Path | str | None = None,
fpmask_filename_format: str | None = None,
angle: float = 0,
shift: tuple = (0, 0),
**kwargs
):
logger.debug("Initialising FPMask with {}".format(maskname))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
logger.debug("Initialising FPMask with {}".format(maskname))
logger.debug("Initialising FPMask with %s", maskname)

(that way the formatting is only executed when debug logging is actually on)

self.name = maskname
self.angle = angle
self.shift = shift
self.xpix = []
self.ypix = []
if maskname == "open":
self.holehdu = fits.ImageHDU()
self.holehdu.header.update(self.hdr)
self.opaquehdu = None
else:
# Try to find the file as a path
if find_file(maskname, silent=True) is None:
file_format = from_currsys(fpmask_filename_format)
self.filename = file_format.format(maskname)
else:
self.filename = maskname

self.data_container = DataContainer(filename=self.filename, **kwargs)
self.pixarea = (self.hdr['CDELT1'] * u.Unit(self.hdr['CUNIT1'])
* self.hdr['CDELT2'] * u.Unit(self.hdr['CUNIT2']))
self.make_hdus(header=self.hdr)


def make_hdus(self, header):
"""Create an hdu for the holes in fpmask

The holes are assumed to be unresolved. They therefore cover one pixel and have
a value corresponding to the actual solid angle covered by the hole.
"""
holehdu = fits.ImageHDU()
holehdu.header.update(header)
holehdu.data = np.zeros((2047, 2047))

opaquehdu = fits.ImageHDU()
opaquehdu.header.update(header)
opaquehdu.data = np.ones((2047, 2047)) * self.pixarea.value

# Hole locations
tab = self.data_container.table
xhole = tab['x'].data
yhole = tab['y'].data
diam = tab['diam'].data

if self.angle != 0:
rangle = np.deg2rad(self.angle)
xtmp = xhole * np.cos(rangle) - yhole * np.sin(rangle)
ytmp = xhole * np.sin(rangle) + yhole * np.cos(rangle)
xhole = xtmp
yhole = ytmp

Check warning on line 93 in scopesim/effects/metis_wcu/fpmask.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_wcu/fpmask.py#L89-L93

Added lines #L89 - L93 were not covered by tests

xhole += self.shift[0]
yhole += self.shift[1]

xpix = (xhole - header['CRVAL1']) / header['CDELT1'] + header['CRPIX1'] - 1
ypix = (yhole - header['CRVAL2']) / header['CDELT2'] + header['CRPIX2'] - 1
in_field = (xpix > 0) * (xpix < 2047) * (ypix > 0) * (ypix < 2047)


for x, y, d in zip(xpix[in_field], ypix[in_field], diam[in_field]):
holearea = (d/2)**2 * np.pi
xint, yint, fracs = sub_pixel_fractions(x, y)
holehdu.data[yint, xint] = np.array(fracs) * holearea
opaquehdu.data[yint, xint] = 0
self.xpix = xpix
self.ypix = ypix
self.holehdu = holehdu
self.opaquehdu = opaquehdu


def plot(self):
"""Plot the location of the holes"""
plt.plot(self.xpix, self.ypix, 'o')
plt.xlim(0, 2048)
plt.ylim(0, 2048)
plt.gca().set_aspect('equal')
plt.show()

Check warning on line 120 in scopesim/effects/metis_wcu/fpmask.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_wcu/fpmask.py#L116-L120

Added lines #L116 - L120 were not covered by tests
Comment on lines +116 to +120
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps use utils.figure_factory() (and through that the "fig, ax" interface) instead? I'm always trying to not include direct script-like plt. calls anywhere, as those can result in plotting over other figures...


def __str__(self) -> str:
return f"""{self.__class__.__name__}: "{self.name}"

Check warning on line 123 in scopesim/effects/metis_wcu/fpmask.py

View check run for this annotation

Codecov / codecov/patch

scopesim/effects/metis_wcu/fpmask.py#L123

Added line #L123 was not covered by tests
Angle: {self.angle} deg
Shift: {self.shift} arcsec"""
Loading
Loading