Skip to content

Commit

Permalink
Merge pull request #275 from AstarVienna/dev_master
Browse files Browse the repository at this point in the history
Release 0.6.2
  • Loading branch information
hugobuddel authored Sep 14, 2023
2 parents 6a23ee2 + 9e7e65e commit c1e65aa
Show file tree
Hide file tree
Showing 37 changed files with 797 additions and 796 deletions.
5 changes: 4 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.1"
version = "0.6.2"
description = "Generalised telescope observation simulator"
readme = "README.md"
requires-python = ">=3.8"
Expand Down Expand Up @@ -43,13 +43,15 @@ dependencies = [
dev = [
"jupyter",
"jupytext",
"ipykernel",
]
test = [
"pytest>=5.0.0",
"pytest-cov",
"scopesim_templates>=0.4.4",
# Just so that readthedocs doesn't include the tests module - yes it's hacky
"skycalc_cli",
"ipykernel",
]
docs = [
"sphinx>=4.3.0",
Expand All @@ -59,6 +61,7 @@ docs = [
"nbsphinx",
"numpydoc",
"scopesim_templates>=0.4.4",
"ipykernel"
]

[project.urls]
Expand Down
18 changes: 7 additions & 11 deletions scopesim/commands/user_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,10 @@ def __init__(self, **kwargs):

def update(self, **kwargs):
"""
Updates the current parameters with a yaml dictionary
Update the current parameters with a yaml dictionary.
See the ``UserCommands`` main docstring for acceptable kwargs
"""

if "use_instrument" in kwargs:
self.package_name = kwargs["use_instrument"]
self.update(packages=[kwargs["use_instrument"]],
Expand Down Expand Up @@ -279,10 +278,9 @@ def _repr_pretty_(self, p, cycle):
else:
p.text(str(self))


def check_for_updates(package_name):
"""
Asks IRDB server if there are newer versions of the instrument package
"""
"""Ask IRDB server if there are newer versions of instrument package."""
response = {}

# tracking **exclusively** your IP address for our internal stats
Expand All @@ -298,7 +296,7 @@ def check_for_updates(package_name):


def patch_fake_symlinks(path: Path):
"""Fixes broken symlinks in path.
"""Fix broken symlinks in path.
The irdb has some symlinks in it, which work fine under linux, but not
always under windows, see https://stackoverflow.com/a/11664406 .
Expand Down Expand Up @@ -345,7 +343,7 @@ def patch_fake_symlinks(path: Path):

def add_packages_to_rc_search(local_path, package_list):
"""
Adds the paths of a list of locally saved packages to the search path list
Add the paths of a list of locally saved packages to the search path list.
Parameters
----------
Expand Down Expand Up @@ -375,7 +373,7 @@ def add_packages_to_rc_search(local_path, package_list):

def load_yaml_dicts(filename):
"""
Loads one or more dicts stored in a YAML file under ``filename``
Load one or more dicts stored in a YAML file under `filename`.
Parameters
----------
Expand All @@ -388,7 +386,6 @@ def load_yaml_dicts(filename):
A list of dicts
"""

yaml_dicts = []
with open(filename) as f:
yaml_dicts += [dic for dic in yaml.full_load_all(f)]
Expand All @@ -398,7 +395,7 @@ def load_yaml_dicts(filename):

def list_local_packages(action="display"):
"""
Lists the packages on the local disk that ScopeSim can find
List the packages on the local disk that ScopeSim can find.
Packages can only be found in the directory listed under::
Expand Down Expand Up @@ -428,7 +425,6 @@ def list_local_packages(action="display"):
If action="return": Lists containing the names of locally saved packages
"""

local_path = Path(rc.__config__["!SIM.file.local_packages_path"]).absolute()
pkgs = [d for d in local_path.iterdir() if d.is_dir()]

Expand Down
9 changes: 3 additions & 6 deletions scopesim/detector/detector_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, detector_list=None, **kwargs):

def readout(self, image_planes, array_effects=None, dtcr_effects=None, **kwargs):
"""
Read out the detector array into a FITS file
Read out the detector array into a FITS file.
Parameters
----------
Expand All @@ -39,7 +39,6 @@ def readout(self, image_planes, array_effects=None, dtcr_effects=None, **kwargs)
self.latest_exposure : fits.HDUList
"""

# .. note:: Detector is what used to be called Chip
# DetectorArray is the old Detector

Expand Down Expand Up @@ -95,8 +94,6 @@ def readout(self, image_planes, array_effects=None, dtcr_effects=None, **kwargs)
for effect in self.array_effects:
image_plane = effect.apply_to(image_plane, **self.meta)



self.latest_exposure = hdu_list

return self.latest_exposure
Expand All @@ -110,15 +107,15 @@ def __str__(self):
return f"{self.__class__.__name__} with {self.detector_list!s}"

def _repr_pretty_(self, p, cycle):
"""For ipython"""
"""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"""
"""Create the primary header from meta data."""
new_meta = utils.stringify_dict(meta)
prihdu = fits.PrimaryHDU()
prihdu.header.update(new_meta)
Expand Down
55 changes: 31 additions & 24 deletions scopesim/effects/apertures.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Effects related to field masks, including spectroscopic slits"""
"""Effects related to field masks, including spectroscopic slits."""

from pathlib import Path
import logging
Expand All @@ -20,7 +20,7 @@

class ApertureMask(Effect):
"""
Only provides the on-sky window coords of the Aperture
Only provides the on-sky window coords of the Aperture.
- Case: Imaging
- Covers the whole FOV of the detector
Expand Down Expand Up @@ -75,6 +75,7 @@ class ApertureMask(Effect):
An integer to identify the ``ApertureMask`` in a list of apertures
"""

def __init__(self, **kwargs):
if not np.any([key in kwargs for key in ["filename", "table",
"array_dict"]]):
Expand Down Expand Up @@ -107,9 +108,12 @@ def __init__(self, **kwargs):
check_keys(kwargs, self.required_keys, "warning", all_any="any")

def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FOVSetupBase):
x = quantity_from_table("x", self.table, u.arcsec).to(u.arcsec).value
y = quantity_from_table("y", self.table, u.arcsec).to(u.arcsec).value
x = quantity_from_table("x", self.table,
u.arcsec).to(u.arcsec).value
y = quantity_from_table("y", self.table,
u.arcsec).to(u.arcsec).value
obj.shrink(["x", "y"], ([min(x), max(x)], [min(y), max(y)]))

# ..todo: HUGE HACK - Get rid of this!
Expand All @@ -121,7 +125,7 @@ def apply_to(self, obj, **kwargs):

# Outdated. Remove when removing all old FOVManager code from effects
def fov_grid(self, which="edges", **kwargs):
""" Returns a header with the sky coordinates """
"""Return a header with the sky coordinates."""
logging.warning("DetectorList.fov_grid will be depreciated in v1.0")
if which == "edges":
self.meta.update(kwargs)
Expand Down Expand Up @@ -162,7 +166,7 @@ def mask(self):

def get_mask(self):
"""
For placing over FOVs if the Aperture is rotated w.r.t. the field
For placing over FOVs if the Aperture is rotated w.r.t. the field.
"""
self.meta = from_currsys(self.meta)

Expand Down Expand Up @@ -193,8 +197,8 @@ def plot(self, axes=None):
class RectangularApertureMask(ApertureMask):
def __init__(self, **kwargs):
super().__init__(**kwargs)
params = {"x_unit" : "arcsec",
"y_unit" : "arcsec"}
params = {"x_unit": "arcsec",
"y_unit": "arcsec"}
self.meta.update(params)
self.meta.update(kwargs)
check_keys(self.meta, ["x", "y", "width", "height"])
Expand Down Expand Up @@ -226,7 +230,7 @@ def get_table(self, **kwargs):

class ApertureList(Effect):
"""
A list of apertures, useful for IFU or MOS instruments
A list of apertures, useful for IFU or MOS instruments.
Parameters
----------
Expand Down Expand Up @@ -255,9 +259,9 @@ class ApertureList(Effect):
optional column ``offset`` may be added. This column describes the offset
from 0 deg to the angle where the first corner is set.
Additionally, the filename of an ``ApertureMask`` polygon file can be given.
The geometry of the polygon defined in the file will be scaled to fit
inside the edges of the row.
Additionally, the filename of an ``ApertureMask`` polygon file can be
given. The geometry of the polygon defined in the file will be scaled to
fit inside the edges of the row.
.. note:: ``shape`` values ``"rect"`` and ``4`` do not produce equal results
Expand All @@ -269,6 +273,7 @@ class ApertureList(Effect):
"""

def __init__(self, **kwargs):
super().__init__(**kwargs)
params = {"pixel_scale": "!INST.pixel_scale",
Expand All @@ -287,11 +292,12 @@ def __init__(self, **kwargs):
check_keys(self.table.colnames, required_keys)

def apply_to(self, obj, **kwargs):
"""See parent docstring."""
if isinstance(obj, FOVSetupBase):
new_vols = []
for row in self.table:
vols = obj.extract(["x", "y"], ([row["left"], row["right"]],
[row["bottom"], row["top"] ]))
[row["bottom"], row["top"]]))
for vol in vols:
vol["meta"]["aperture_id"] = row["id"]

Expand Down Expand Up @@ -380,10 +386,9 @@ def __add__(self, other):
# return self.get_apertures(item)[0]



class SlitWheel(Effect):
"""
A selection of predefined spectroscopic slits and possibly other field masks
Selection of predefined spectroscopic slits and possibly other field masks.
It should contain an open position.
A user can define a non-standard slit by directly using the Aperture
Expand Down Expand Up @@ -448,14 +453,15 @@ def __init__(self, **kwargs):
self.table = self.get_table()

def apply_to(self, obj, **kwargs):
"""Use apply_to of current_slit"""
"""Use apply_to of current_slit."""
return self.current_slit.apply_to(obj, **kwargs)

def fov_grid(self, which="edges", **kwargs):
"""See parent docstring."""
return self.current_slit.fov_grid(which=which, **kwargs)

def change_slit(self, slitname=None):
"""Change the current slit"""
"""Change the current slit."""
if not slitname or slitname in self.slits.keys():
self.meta["current_slit"] = slitname
self.include = slitname
Expand All @@ -464,13 +470,13 @@ def change_slit(self, slitname=None):

def add_slit(self, newslit, name=None):
"""
Add a slit to the SlitWheel
Add a slit to the SlitWheel.
Parameters
==========
----------
newslit : Slit
name : string
Name to be used for the new slit. If `None`, a name from
Name to be used for the new slit. If ``None``, a name from
the newslit object is used.
"""
if name is None:
Expand All @@ -479,7 +485,7 @@ def add_slit(self, newslit, name=None):

@property
def current_slit(self):
"""Return the currently used slit"""
"""Return the currently used slit."""
currslit = from_currsys(self.meta["current_slit"])
if not currslit:
return False
Expand All @@ -490,7 +496,7 @@ def __getattr__(self, item):

def get_table(self):
"""
Create a table of slits with centre position, width and length
Create a table of slits with centre position, width and length.
Width is defined as the extension in the y-direction, length in the
x-direction. All values are in milliarcsec.
Expand Down Expand Up @@ -519,7 +525,7 @@ def get_table(self):
return tbl


################################################################################
###############################################################################


def make_aperture_polygon(left, right, top, bottom, angle, shape, **kwargs):
Expand Down Expand Up @@ -577,7 +583,8 @@ def mask_from_coords(x, y, pixel_scale):


def rotate(x, y, x0, y0, angle):
""" Rotate a line by ``angle`` [deg] around the point (x0, y0) """
"""Rotate a line by `angle` [deg] around the point (`x0`, `y0`)."""
# TODO: isn't that just a rotation matrix?
angle_rad = angle / 57.29578
xnew = x0 + (x - x0) * np.cos(angle_rad) - (y - y0) * np.sin(angle_rad)
ynew = y0 + (x - x0) * np.sin(angle_rad) + (y - y0) * np.cos(angle_rad)
Expand Down
Loading

0 comments on commit c1e65aa

Please sign in to comment.