1 """! representation of alignment parameters"""
8 Representation of a single alignment parameter
10 This class also contains helpful functions for operating on sets of alignment
11 parameters e.g. parsing the map file or pede res file
16 pede ID number as written in compact.xml, pede steering, and map files
18 human-readable name as written in map file
20 1 is for top and 2 is for bottom
22 1 is for translation and 2 is for rotation
24 1 is for 'u', 2 is for v, and 3 is for w
26 "layer" ID number in millepede (i.e. axial and stereo sensors are separated)
28 value of parameter (if loaded from res file)
30 error of parameter (if loaded from res file)
32 true if parameter is floating, false otherwise
35 idn_str_pattern = re.compile(
'^[12][123][123][0-9][0-9]$')
36 layer_number_pattern = re.compile(
'^.*_L([0-9]).*$')
38 def __init__(self, idn, name, half, trans_rot, direction, mp_layer_id):
39 self.
_id_id = int(idn)
51 """!Set whether this parameter is floating/active or not"""
55 """!Get the module number from the millepede layer number
57 We group sensors in pairs to form modules and the layer number
58 for millepede counts up from the furthest upstream sensor. Thus,
59 we do integer-division by two to get the module number.
67 """!Get the human layer number
69 Since, for the 2016 parameter mapping, a typo led to a dis-association between
70 the module number deduced from the ID number and the layer number, we have
71 to extract the layer number from the name of the parameter name as it appears
72 in the mapping. We look for '_L<digit>' and extract <digit> as the layer number.
75 m = Parameter.layer_number_pattern.match(self.
_name_name)
77 raise ValueError(f
'Unable to deduce layer number from name {self.name}')
79 return int(m.group(1))
88 """!Get whether this Parameter represents a single sensor (True)
89 or a structural component holding two or more sensors (False)
94 """!True if Parameter represents a translation"""
98 """!True if Parameter represents a rotation"""
102 """!Does this parameter represent a component on the top half (True)
105 return (self.
_half_half == 1)
108 """!True if Parameter is in bottom half, False if in top half"""
109 return (self.
_half_half == 2)
112 """!Get whether this Parameter represents a single axial sensor (True)
113 or something else (False)
115 We have to check the name to see if 'axial' is in it.
120 """!Get whether this Parameter represents a single stereo sensor (True)
121 or something else (False)
123 We have to check the name to see if 'stereo' is in it.
128 """!True if Parameter is single sensor in front half, False otherwise"""
132 """!True if Parameter is single sensor in back half, False otherwise"""
136 """!True if Parameter is a single sensor in back half on the hole side, Flase otherwise"""
140 """!True if Parameter is a single sensor in back half on the slot side, Flase otherwise"""
144 """!True if Parameter is active (i.e. floating) and False if not"""
148 """parse a line from the map file
150 we assume that the constructor's arguments are in the same
151 order as a line in the sensor map file
156 """! Deduce the categorical flags from the ID number
158 Each ID number is five digis.
161 [12][12][123][0-9][0-9]
162 | |- last two digis are sensor ID number
163 | |------ direction 1==u, 2==v, 3==w
164 | |---------- transformation 1==translation, 2==rotation
165 |--------------- detector half 1==top, 2==bottom
167 So we just need to break it down by modulo and integer
168 division /OR/ do some str conversion nonsense in python.
173 raise ValueError(f
'Bad ID Number: {idn} is not five digis')
175 if not Parameter.idn_str_pattern.match(idn):
176 raise ValueError(f
'Bad ID Number: {idn} does not match the ID pattern')
181 half = int(digits[0])
182 trans_rot = int(digits[1])
183 direction = int(digits[2])
184 mp_layer_id = int(digits[3]+digits[4])
185 return Parameter(int(idn), idn, half, trans_rot, direction, mp_layer_id)
188 """! load the entire parameter set from a map file
193 map from ID number to a Parameter
196 with open(map_filepath)
as mf:
199 if 'MilleParameter' in line:
201 p = Parameter.from_map_file_line(line)
202 parameters[p.id()] = p
206 """! Assumes line is for the same parameter as stored in self
208 A line in the pede result file has either 3 or 5 columns.
212 3. activity (0.0 if floating, -1.0 if not)
214 5. (if active) error in value
216 We ignore the first column and assume that we are only calling
217 this function if the line has already been deduced to correspond
218 to the parameter we represent.
220 elements = line.split()
224 if len(elements) > 4:
229 """! parse a pede results file
231 Parse the results file into a dictionary. If no destination dictionary
232 is provided, a new dictionary is created with the ID numbers as keys
233 and Parameter instances as values. Since this mapping is created without
234 the sensor mapping, the rest of the Parameter attributes are assigned
240 path to results file we are going to parse
241 destination : dict, optional
242 if provided, load the values from the file into parameters in this dict
243 skip_nonfloat : bool, optional
244 skip non-floating parameters
247 with open(res_file)
as rf:
250 if 'Parameter' in line:
252 idn = int(line.split()[0])
253 if destination
is None:
254 p = Parameter.from_idn(idn)
255 p.__from_res_file_line(line)
256 if p.active()
or not skip_nonfloat:
257 parameters[p.id()] = p
259 if idn
not in destination:
260 raise ValueError(f
'Attempting to load parameter {idn} which is not in parameter map')
261 if destination[idn].
active()
or not skip_nonfloat:
263 return parameters
if destination
is None else None
266 """! Print this parameter as it should appear in the pede steering file"""
267 return f
'{self._id} {self._val} {0.0 if self._active else -1.0} {self._name}'
270 """! Print the value of this parameter as it should be inserted into the compact
272 **including** the operator (either + or -)
274 This is where we handle whether the sign flips (translations) or doesn't (rotations)
277 op =
'+' if self.
_val_val > 0
else '-'
280 op =
'-' if self.
_val_val > 0
else '+'
282 return f
'{op} {abs(self._val)}'
285 """! Representation of this parameter"""
286 return f
'{self.__class__.__name__}({self._id})'
289 """! Human printing of this parameter"""
294 s += f
' {self._val*1000} +- {self._error*1000} um'
298 s += f
' {self._val*1000} +- {self._error*1000} mrad'
Representation of a single alignment parameter.
def parse_map_file(map_filepath)
load the entire parameter set from a map file
def compact_value(self)
Print the value of this parameter as it should be inserted into the compact.
def active(self)
True if Parameter is active (i.e.
def __str__(self)
Human printing of this parameter.
def translation(self)
True if Parameter represents a translation.
def layer(self)
Get the human layer number.
def bottom(self)
True if Parameter is in bottom half, False if in top half.
def __from_res_file_line(self, line)
Assumes line is for the same parameter as stored in self.
def slot(self)
True if Parameter is a single sensor in back half on the slot side, Flase otherwise.
def back(self)
True if Parameter is single sensor in back half, False otherwise.
def axial(self)
Get whether this Parameter represents a single axial sensor (True) or something else (False)
def top(self)
Does this parameter represent a component on the top half (True) or bottom (False)
def parse_pede_res(res_file, destination=None, skip_nonfloat=False)
parse a pede results file
def from_map_file_line(line)
def rotation(self)
True if Parameter represents a rotation.
def from_idn(idn)
Deduce the categorical flags from the ID number.
def float(self, yes=True)
Set whether this parameter is floating/active or not.
def module(self)
Get the module number from the millepede layer number.
def __repr__(self)
Representation of this parameter.
def front(self)
True if Parameter is single sensor in front half, False otherwise.
def stereo(self)
Get whether this Parameter represents a single stereo sensor (True) or something else (False)
def individual(self)
Get whether this Parameter represents a single sensor (True) or a structural component holding two or...
def pede_format(self)
Print this parameter as it should appear in the pede steering file.
def __init__(self, idn, name, half, trans_rot, direction, mp_layer_id)
def hole(self)
True if Parameter is a single sensor in back half on the hole side, Flase otherwise.