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

1"""Sets based in daiquiri hardware objects 

2""" 

3 

4import numpy 

5from daiquiri.core.transform import maps 

6from daiquiri.core.transform import hw_sets 

7from daiquiri.core.transform import units 

8 

9 

10class MotorLinearCombination(maps.AxisLinearCombination): 

11 """For example: 

12 y(nm) = samy(mm) + sampy(um) + offset(nm) 

13 """ 

14 

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 

25 

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 ) 

40 

41 @property 

42 def offset(self): 

43 if self._offset_cache is None: 

44 self._offset_cache = self._offset.to(self.units).magnitude 

45 

46 return self._offset_cache 

47 

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 

52 

53 def _parse_matrix(self, motors): 

54 """ 

55 :param list motors: 

56 """ 

57 return None 

58 

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) 

66 

67 def _calc_coefficient(self, mot): 

68 """Calculate the motor coefficient from the motor units and destination units 

69 

70 :param Motor mot: 

71 :returns num: 

72 """ 

73 if mot.id() in self._coeff_cache: 

74 return self._coeff_cache[mot.id()] 

75 

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 

82 

83 self._coeff_cache[mot.id()] = coeff 

84 return coeff 

85 

86 @property 

87 def default_reference(self): 

88 return self.domain.current_position 

89 

90 def codomain_limits(self, motname, reference=None): 

91 """Limits projected on the codmain 

92 

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) 

99 

100 @property 

101 def current_domain_position(self): 

102 return self.domain.current_position 

103 

104 @property 

105 def current_codomain_position(self): 

106 return self.forward(self.current_domain_position)