__all__ = ["Arrangement"]
from typing import Dict, Union
import numpy as np
from ._tune import Tune
from ._discrete_tune import DiscreteTune
def mktune(dict_):
if "ranges" in dict_:
return DiscreteTune(**dict_)
return Tune(**dict_)
[docs]
class Arrangement:
[docs]
def __init__(self, name: str, tunes: Dict[str, Union[DiscreteTune, Tune, dict]]):
"""Arrangement of several Tunes to form one cohesive set.
Tunes may represent either motors or other arrangements, however
semantic meaning is provided by the Instrument which contains the
Arrangement, to the arrangement, they are all string keys mapped to tunes.
All tunes *must* have the same independent units, and must overlap.
Parameters
----------
name: str
A name for this Arrangement, used to identify this Arrangement
from other Arrangements which may depend on this one.
tunes: Dict[str, Tune]
Mapping of names to Tune objects which compose the Arrangement
"""
self._name: str = name
self._tunes: Dict[str, Union[DiscreteTune, Tune]] = {
k: mktune(v) if isinstance(v, dict) else v for k, v in tunes.items()
}
self._ind_units: str = "nm"
def __repr__(self):
return f"Arrangement({repr(self.name)}, {repr(self.tunes)})"
def __getitem__(self, key):
return self.tunes[key]
def __eq__(self, other):
if self.name != other.name:
return False
if self.tunes != other.tunes:
return False
return True
@property
def independent(self):
"""Returns a 1-dimensional numpy array with the set of all unique independent points.
Points closer together than 1/1000th of the total dynamic range are considered identical.
Only returns points within range of all tunes.
"""
out = np.unique(
np.concatenate([t.independent for t in self._tunes.values() if isinstance(t, Tune)], 0)
)
tol = 1e-3 * (self.ind_max - self.ind_min)
diff = np.append(tol * 2, np.diff(out))
out = out[diff > tol]
out = out[out <= self.ind_max]
out = out[out >= self.ind_min]
return out
[docs]
def keys(self):
"""Return the names of the tunes in the arrangment."""
return self.tunes.keys()
[docs]
def values(self):
"""Return the tunes in the arrangment."""
return self.tunes.values()
[docs]
def items(self):
"""Return the names and tunes in the arrangment."""
return self.tunes.items()
[docs]
def as_dict(self):
"""Dictionary representation of the Arrangement"""
out = {}
out["name"] = self._name
out["tunes"] = {k: v.as_dict() for k, v in self._tunes.items()}
return out
@property
def ind_max(self):
"""The maximum independant (input) value for this arrangement."""
return min([t.ind_max for t in self._tunes.values() if isinstance(t, Tune)])
@property
def ind_min(self):
"""The minimum independant (input) value for this arrangement."""
return max([t.ind_min for t in self._tunes.values() if isinstance(t, Tune)])
@property
def name(self):
"""The name of the arrangement."""
return self._name
@property
def tunes(self):
"""The tunes in the arrangement."""
return self._tunes