Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/core/transform/hw_maps.py: 89%
56 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-14 02:13 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-14 02:13 +0000
1"""Sets based in daiquiri hardware objects
2"""
4import numpy
5from daiquiri.core.transform import maps
6from daiquiri.core.transform import hw_sets
7from daiquiri.core.transform import units
10class MotorLinearCombination(maps.AxisLinearCombination):
11 """For example:
12 y(nm) = samy(mm) + sampy(um) + offset(nm)
13 """
15 def __init__(self, motors, offset=0, units=None, unitdict=None, closed=None):
16 """
17 :param list(Motor) motors:
18 :param num or Quantity offset: codomain values are in these units
19 :param str or Unit units: codomain units
20 :param dict unitdict: motor units (override the unit attribute of the motor object)
21 :param list(2-tuple(bool)) closed: min/max included or not for each motor
22 """
23 self._coeff_cache = {}
24 self._offset_cache = None
26 if units is None:
27 if units.isquantity(offset):
28 self.units = offset.unit
29 else:
30 raise ValueError("Missing transformation destination units")
31 else:
32 self.units = units
33 if unitdict is None:
34 unitdict = {}
35 self.unitdict = unitdict
36 domain = hw_sets.MotorDomain(motors, closed=closed)
37 super(maps.AxisLinearCombination, self).__init__(
38 domain=domain, coefficients=motors, offset=offset
39 )
41 @property
42 def offset(self):
43 if self._offset_cache is None:
44 self._offset_cache = self._offset.to(self.units).magnitude
46 return self._offset_cache
48 @offset.setter
49 def offset(self, value):
50 self._offset = units.asquantity(value, self.units)
51 self._offset_cache = self._offset.to(self.units).magnitude
53 def _parse_matrix(self, motors):
54 """
55 :param list motors:
56 """
57 return None
59 @property
60 def matrix(self):
61 """
62 :returns array: shape (1, domain.ndim)
63 """
64 matrix = [self._calc_coefficient(mot) for mot in self.domain.motors]
65 return numpy.atleast_2d(matrix)
67 def _calc_coefficient(self, mot):
68 """Calculate the motor coefficient from the motor units and destination units
70 :param Motor mot:
71 :returns num:
72 """
73 if mot.id() in self._coeff_cache:
74 return self._coeff_cache[mot.id()]
76 u = self.unitdict.get(mot.id())
77 if u is None:
78 u = mot.get("unit")
79 if u is None:
80 raise AttributeError(f"Motor {mot.name()} does not have a unit")
81 coeff = units.asquantity(1, u).to(self.units).magnitude
83 self._coeff_cache[mot.id()] = coeff
84 return coeff
86 @property
87 def default_reference(self):
88 return self.domain.current_position
90 def codomain_limits(self, motname, reference=None):
91 """Limits projected on the codmain
93 :param str motname:
94 :param array reference: shape is (1, ndomain)
95 :returns array-like: shape is (2,)
96 """
97 axis = self.domain.motor_index(motname)
98 return super().codomain_limits(axis, reference=reference)
100 @property
101 def current_domain_position(self):
102 return self.domain.current_position
104 @property
105 def current_codomain_position(self):
106 return self.forward(self.current_domain_position)