Skip to content

Commit

Permalink
Merge pull request #268 from AstarVienna/dev_master
Browse files Browse the repository at this point in the history
Release v0.6.1
  • Loading branch information
hugobuddel authored Sep 6, 2023
2 parents 6149822 + e5c1e3d commit 6a23ee2
Show file tree
Hide file tree
Showing 36 changed files with 1,389 additions and 995 deletions.
11 changes: 9 additions & 2 deletions .github/workflows/notebooks_with_irdb_download.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ jobs:
# that users have with ScopeSim / IRDB.
# However, only use minimum and maximum supported Python version,
# as the IRDB download often fails.
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.11']
# As of 2023/07/19, this test still often fails. See
# https://github.com/AstarVienna/ScopeSim/issues/254
# For now, only run on one configuration, as having one green test
# is more useful than 5 green and one red. The others can be enabled
# once we fix the problem properly.
# os: [ubuntu-latest, windows-latest, macos-latest]
# python-version: ['3.8', '3.11']
os: [ubuntu-latest]
python-version: ['3.11']

steps:
- uses: actions/checkout@v3
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "ScopeSim"
version = "0.6.0"
version = "0.6.1"
description = "Generalised telescope observation simulator"
readme = "README.md"
requires-python = ">=3.8"
Expand Down Expand Up @@ -58,6 +58,7 @@ docs = [
"sphinxcontrib-apidoc",
"nbsphinx",
"numpydoc",
"scopesim_templates>=0.4.4",
]

[project.urls]
Expand Down
13 changes: 13 additions & 0 deletions scopesim/commands/user_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ def set_modes(self, modes=None):
for mode in modes:
if mode in self.modes_dict:
defyam["properties"]["modes"].append(mode)
if "deprecate" in self.modes_dict[mode]:
logging.warning(self.modes_dict[mode]["deprecate"])
else:
raise ValueError(f"mode '{mode}' was not recognised")

Expand All @@ -243,6 +245,8 @@ def list_modes(self):
dic = self.modes_dict[mode_name]
desc = dic["description"] if "description" in dic else "<None>"
modes[mode_name] = desc
if "deprecate" in dic:
modes[mode_name] += " (deprecated)"

msg = "\n".join([f"{key}: {value}" for key, value in modes.items()])
else:
Expand All @@ -265,6 +269,15 @@ def __contains__(self, item):
def __repr__(self):
return f"{self.__class__.__name__}(**{self.kwargs!r})"

def __str__(self):
return str(self.cmds)

def _repr_pretty_(self, p, cycle):
"""For ipython"""
if cycle:
p.text("UserCommands(...)")
else:
p.text(str(self))

def check_for_updates(package_name):
"""
Expand Down
21 changes: 18 additions & 3 deletions scopesim/detector/detector_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, detector_list=None, **kwargs):
self.detectors = []
self.latest_exposure = None

def readout(self, image_planes, array_effects=[], dtcr_effects=[], **kwargs):
def readout(self, image_planes, array_effects=None, dtcr_effects=None, **kwargs):
"""
Read out the detector array into a FITS file
Expand Down Expand Up @@ -54,8 +54,8 @@ def readout(self, image_planes, array_effects=[], dtcr_effects=[], **kwargs):
# - add ImageHDUs
# - add ASCIITableHDU with Effects meta data in final table extension

self.array_effects = array_effects
self.dtcr_effects = dtcr_effects
self.array_effects = array_effects or []
self.dtcr_effects = dtcr_effects or []
self.meta.update(kwargs)

# 0. Get the image plane that corresponds to this detector array
Expand Down Expand Up @@ -101,6 +101,21 @@ def readout(self, image_planes, array_effects=[], dtcr_effects=[], **kwargs):

return self.latest_exposure

def __repr__(self):
msg = (f"{self.__class__.__name__}"
f"({self.detector_list!r}, **{self.meta!r})")
return msg

def __str__(self):
return f"{self.__class__.__name__} with {self.detector_list!s}"

def _repr_pretty_(self, p, cycle):
"""For ipython"""
if cycle:
p.text(f"{self.__class__.__name__}(...)")
else:
p.text(str(self))


def make_primary_hdu(meta):
"""Create the primary header from meta data"""
Expand Down
63 changes: 31 additions & 32 deletions scopesim/effects/apertures.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from ..optics import image_plane_utils as imp_utils
from ..base_classes import FOVSetupBase

from ..utils import quantify, quantity_from_table, from_currsys, check_keys
from ..utils import quantify, quantity_from_table, from_currsys, check_keys, \
figure_factory


class ApertureMask(Effect):
Expand Down Expand Up @@ -83,7 +84,7 @@ def __init__(self, **kwargs):
w, h = kwargs["width"], kwargs["height"]
kwargs["filename"] = kwargs["filename_format"].format(w, h)

super(ApertureMask, self).__init__(**kwargs)
super().__init__(**kwargs)
params = {"pixel_scale": "!INST.pixel_scale",
"no_mask": True,
"angle": 0,
Expand Down Expand Up @@ -175,22 +176,23 @@ def get_mask(self):

return mask

def plot(self, new_figure=True):
import matplotlib.pyplot as plt
if new_figure:
plt.gcf().clf()
def plot(self, axes=None):
if axes is None:
fig, ax = figure_factory()
else:
fig = axes.figure

x = list(self.table["x"].data)
y = list(self.table["y"].data)
plt.plot(x + [x[0]], y + [y[0]])
plt.gca().set_aspect("equal")
ax.plot(x + [x[0]], y + [y[0]])
ax.set_aspect("equal")

return plt.gcf()
return fig


class RectangularApertureMask(ApertureMask):
def __init__(self, **kwargs):
super(RectangularApertureMask, self).__init__(**kwargs)
super().__init__(**kwargs)
params = {"x_unit" : "arcsec",
"y_unit" : "arcsec"}
self.meta.update(params)
Expand Down Expand Up @@ -268,7 +270,7 @@ class ApertureList(Effect):
"""
def __init__(self, **kwargs):
super(ApertureList, self).__init__(**kwargs)
super().__init__(**kwargs)
params = {"pixel_scale": "!INST.pixel_scale",
"n_round_corners": 32, # number of corners use to estimate ellipse
"no_mask": False, # .. todo:: is this necessary when we have conserve_image?
Expand Down Expand Up @@ -342,26 +344,27 @@ def get_apertures(self, row_ids):
return apertures_list

def plot(self):
import matplotlib.pyplot as plt
plt.gcf().clf()
fig, ax = figure_factory()

for ap in self.apertures:
ap.plot(new_figure=False)
ap.plot(ax)

return plt.gcf()
return fig

def plot_masks(self):
import matplotlib.pyplot as plt

aps = self.apertures
n = len(aps)
w = np.ceil(n ** 0.5).astype(int)
assert int(n ** 0.5) == w + 1
h = np.ceil(n / w).astype(int)
assert int(n / w) == h + 1
# TODO: change these?

for ii, ap in enumerate(aps):
plt.subplot(w, h, ii + 1)
plt.imshow(ap.mask.T)
plt.show()
fig, axes = figure_factory(w, h)
for ap, ax in zip(aps, axes):
ax.imshow(ap.mask.T)
fig.show()
return fig

def __add__(self, other):
if isinstance(other, ApertureList):
Expand Down Expand Up @@ -419,11 +422,13 @@ class SlitWheel(Effect):
current_slit: "C"
"""
def __init__(self, **kwargs):
required_keys = ["slit_names", "filename_format", "current_slit"]
check_keys(kwargs, required_keys, action="error")

super(SlitWheel, self).__init__(**kwargs)
required_keys = {"slit_names", "filename_format", "current_slit"}
_current_str = "current_slit"

def __init__(self, **kwargs):
super().__init__(**kwargs)
check_keys(kwargs, self.required_keys, action="error")

params = {"z_order": [80, 280, 580],
"path": "",
Expand All @@ -433,7 +438,7 @@ def __init__(self, **kwargs):
self.meta.update(params)
self.meta.update(kwargs)

path = Path(self.meta["path"], from_currsys(self.meta["filename_format"]))
path = self._get_path()
self.slits = {}
for name in from_currsys(self.meta["slit_names"]):
kwargs["name"] = name
Expand Down Expand Up @@ -480,12 +485,6 @@ def current_slit(self):
return False
return self.slits[currslit]

@property
def display_name(self):
return f"{self.meta['name']} : " \
f"[{from_currsys(self.meta['current_slit'])}]"


def __getattr__(self, item):
return getattr(self.current_slit, item)

Expand Down
26 changes: 13 additions & 13 deletions scopesim/effects/detector_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .effects import Effect
from .apertures import ApertureMask
from .. import utils
from ..utils import close_loop, figure_factory
from ..optics.image_plane_utils import header_from_list_of_xy, calc_footprint

__all__ = ["DetectorList", "DetectorWindow"]
Expand Down Expand Up @@ -105,7 +106,7 @@ class : DetectorList
"""
def __init__(self, **kwargs):
super(DetectorList, self).__init__(**kwargs)
super().__init__(**kwargs)
params = {"z_order": [90, 290, 390, 490],
"pixel_scale": "!INST.pixel_scale", # arcsec
"active_detectors": "all",
Expand Down Expand Up @@ -251,22 +252,21 @@ def detector_headers(self, ids=None):

return hdrs

def plot(self):
import matplotlib.pyplot as plt
plt.gcf().clf()
def plot(self, axes=None):
if axes is None:
_, axes = figure_factory()

for hdr in self.detector_headers():
x_mm, y_mm = calc_footprint(hdr, "D")
x_cen, y_cen = np.average(x_mm), np.average(y_mm)
x_mm = list(x_mm) + [x_mm[0]]
y_mm = list(y_mm) + [y_mm[0]]
plt.gca().plot(x_mm, y_mm)
plt.gca().text(x_cen, y_cen, hdr["ID"])
axes.plot(list(close_loop(x_mm)), list(close_loop(y_mm)))
axes.text(*np.mean((x_mm, y_mm), axis=1), hdr["ID"],
ha="center", va="center")

plt.gca().set_aspect("equal")
plt.ylabel("Size [mm]")
axes.set_aspect("equal")
axes.set_xlabel("Size [mm]")
axes.set_ylabel("Size [mm]")

return plt.gcf()
return axes


class DetectorWindow(DetectorList):
Expand Down Expand Up @@ -314,4 +314,4 @@ def __init__(self, pixel_size, x, y, width, height=None, angle=0, gain=1,
"angle", "gain", "pixel_size"])
tbl.meta.update(params)

super(DetectorWindow, self).__init__(table=tbl, **params)
super().__init__(table=tbl, **params)
Loading

0 comments on commit 6a23ee2

Please sign in to comment.