Skip to content

Commit

Permalink
Add support for package and mode status keywords (#509)
Browse files Browse the repository at this point in the history
  • Loading branch information
teutoburg authored Nov 25, 2024
2 parents fbe8ce9 + 4192891 commit 4309816
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 6 deletions.
51 changes: 47 additions & 4 deletions scopesim/commands/user_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ def __init__(self, *maps, **kwargs):
self._kwargs = deepcopy(kwargs)
self.ignore_effects = []
self.package_name = ""
self.package_status = ""
self.default_yamls = []
self.modes_dict = {}

Expand Down Expand Up @@ -201,6 +202,25 @@ def _load_yaml_dict(self, yaml_dict):
if "mode_yamls" in yaml_dict:
logger.debug(" found mode_yamls")
self.update(mode_yamls=yaml_dict["mode_yamls"])

if yaml_dict.get("object", "") == "configuration":
# we're in default.yaml
self.package_status = yaml_dict.get("status", "unknown")
if self.package_status == "deprecated":
warn("The selected instrument package is deprecated!",
DeprecationWarning, stacklevel=7)
if self.package_status == "concept":
raise NotImplementedError(
"The selected instrument package is not yet supported."
)
if self.package_status == "experimental":
# or rather warning?
logger.info(
"The selected instrument package is still in experimental "
"stage, results may not be representative of physical "
"instrument, use with care."
)

logger.debug(" dict yaml done")

def _load_yamls(self, yamls: Collection) -> None:
Expand Down Expand Up @@ -351,8 +371,24 @@ def set_modes(self, *modes) -> None:
raise ValueError(f"mode '{mode}' was not recognised")

defyam["properties"]["modes"].append(mode)
if depmsg := self.modes_dict[mode].get("deprecate"):
warn(depmsg, DeprecationWarning, stacklevel=2)
if ((msg := self.modes_dict[mode].get("deprecate", "")) or
self.modes_dict[mode].get("status") == "deprecated"):
# Fallback if status: deprecated but not deprecate key
msg = msg or f"Instrument mode '{mode}' is deprecated."
warn(msg, DeprecationWarning, stacklevel=2)

if self.modes_dict[mode].get("status") == "experimental":
# or rather warning?
logger.info(
"Mode '%s' is still in experimental stage, results "
"may not be representative of physical instrument.",
mode
)

if self.modes_dict[mode].get("status") == "concept":
raise NotImplementedError(
f"Instrument mode '{mode}' is not yet supported."
)

# Note: This used to completely reset the instance via the line below.
# Calling init like this is bad design, so I replaced is with a
Expand All @@ -371,8 +407,15 @@ def list_modes(self) -> Iterable[tuple[str, ...]]:
cases, it now returns a generator of tuples of strings.
"""
for mode, subdict in self.modes_dict.items():
desc = (subdict.get("description", "<None>") +
":DEPRECATED" * ("deprecate" in subdict))
# TODO: maybe find a prettier way to print the status...
# TODO: maybe also print mode type (e.g. MICADO SCAO)
desc = (
subdict.get("description", "<None>") +
f":status={subdict.get('status')}" * ("status" in subdict) +
":DEPRECATED" * (
"deprecate" in subdict and "status" not in subdict
)
)
yield mode, *(s.strip() for s in desc.split(":"))

@property
Expand Down
23 changes: 22 additions & 1 deletion scopesim/tests/mocks/basic_instrument/default.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Default config file for setting up the instrument
object : observation
object: configuration
alias : OBS
name : test_instrument
description : default parameters needed for a basic simulation
status: development

packages :
- basic_instrument # name of package dependencies
Expand All @@ -24,6 +25,7 @@ properties :
mode_yamls :
- name : imaging
description: Basic NIR imager
status: development
alias : OBS
properties :
include_slit : False
Expand All @@ -32,6 +34,7 @@ mode_yamls :

- name : spectroscopy
description: Basic three-trace long-slit spectrograph
status: development
alias: OBS
properties :
include_slit : True
Expand All @@ -42,10 +45,28 @@ mode_yamls :

- name : ifu
description: Basic three-trace integral-field-unit spectrograph
status: development
alias: OBS
properties:
include_slit: False
include_slicer: True
filter_name: "open"
yamls:
- YAML_mode_ifu.yaml # mode specific effects and properties

- name: mock_concept_mode
description: Dummy mode to test concept status.
status: concept

- name: mock_experimental_mode
description: Dummy mode to test experimental status.
status: experimental

- name: mock_deprecated_mode
description: Dummy mode to test deprecated status without message.
status: deprecated

- name: mock_deprecated_mode_msg
description: Dummy mode to test deprecated status with message.
status: deprecated
deprecate: This mode is deprecated.
54 changes: 53 additions & 1 deletion scopesim/tests/test_basic_instrument/test_basic_instrument.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

# -*- coding: utf-8 -*-
import pytest

import numpy as np
Expand Down Expand Up @@ -116,6 +116,7 @@ def test_runs(self):
trace_flux = det_im[:, sl].sum() # sum along a trace
assert round(trace_flux / spot_flux) == n


@pytest.mark.usefixtures("protect_currsys", "patch_all_mock_paths")
class TestSourceImageNotAffected:
"""
Expand Down Expand Up @@ -228,6 +229,57 @@ def test_source_keywords_in_header(self):
assert hdr["ESO ATM SEEING"] == opt.cmds["!OBS.psf_fwhm"]


@pytest.mark.usefixtures("protect_currsys", "patch_all_mock_paths")
class TestModeStatus:
def test_concept_mode_init(self):
with pytest.raises(NotImplementedError):
_ = sim.UserCommands(use_instrument="basic_instrument",
set_modes=["mock_concept_mode"])

def test_concept_mode_change(self):
cmd = sim.UserCommands(use_instrument="basic_instrument")
with pytest.raises(NotImplementedError):
cmd.set_modes("mock_concept_mode")

def test_experimental_mode_init(self, caplog):
_ = sim.UserCommands(use_instrument="basic_instrument",
set_modes=["mock_experimental_mode"])
assert ("Mode 'mock_experimental_mode' is still in experimental stage"
in caplog.text)

def test_experimental_mode_change(self, caplog):
cmd = sim.UserCommands(use_instrument="basic_instrument")
cmd.set_modes("mock_experimental_mode")
assert ("Mode 'mock_experimental_mode' is still in experimental stage"
in caplog.text)

def test_deprecated_mode_init(self):
with pytest.raises(
DeprecationWarning,
match="Instrument mode 'mock_deprecated_mode' is deprecated."):
_ = sim.UserCommands(use_instrument="basic_instrument",
set_modes=["mock_deprecated_mode"])

def test_deprecated_mode_change(self):
cmd = sim.UserCommands(use_instrument="basic_instrument")
with pytest.raises(
DeprecationWarning,
match="Instrument mode 'mock_deprecated_mode' is deprecated."):
cmd.set_modes("mock_deprecated_mode")

def test_deprecated_msg_mode_init(self):
with pytest.raises(
DeprecationWarning, match="This mode is deprecated."):
_ = sim.UserCommands(use_instrument="basic_instrument",
set_modes=["mock_deprecated_mode_msg"])

def test_deprecated_msg_mode_change(self, caplog):
cmd = sim.UserCommands(use_instrument="basic_instrument")
with pytest.raises(
DeprecationWarning, match="This mode is deprecated."):
cmd.set_modes("mock_deprecated_mode_msg")


@pytest.fixture(scope="function", name="obs")
def basic_opt_observed():
src = st.star(flux=15)
Expand Down

0 comments on commit 4309816

Please sign in to comment.