HPS-MC
 
Loading...
Searching...
No Matches
_pattern.py
Go to the documentation of this file.
1"""! pattern that can match one or more Parameters"""
2
3from ._parameter import Parameter
4
5
6class Pattern:
7 """! Pattern that can match one or more paramters
8
9 This is an internal class and should not be used outside of this module
10
11 A single "pattern" is a str that is one of the unary keywords OR
12 has a binary keyword followed by an "=" character followed by one
13 of that keywords values. All whitespace in a pattern is removed so
14 spaces can be added for easier readability.
15
16 Syntax
17 ------
18 Each pattern is made up of one or more operations where each operation
19 is separated by an ampersand "&" to reflect that a Pattern takes the
20 logical-and of the operations listed.
21
22 'op1 & op2 & op3 ...'
23
24 Each operation can be one of three things.
25
26 1. An ID number.
27 2. A unary operation.
28 3. A binary operation.
29
30 ID numbers are the 5-digit millepede ID number for that parameter which encodes all
31 of the location information within it. It specifies a single millepede parameter.
32
33 Unary operations are special keywords that correspond to different logical grouping
34 of parameters. Some unary operations correspond to functions returning True/False
35 of the Parameter class while others are simple shortenings of common Pattern strings
36 (a.k.a. "aliases").
37
38 Binary operations are a string formatted like "kw = val" where a *single* equal
39 sign is used. kw is a keyword corresponding to select functions from the Parameter
40 class while val is a keyword corresponding to specific options for each kw.
41 """
42
43 NUM_MODULES = 7
44
46 """!Make sure input is a valid ID number, otherwise return NotImplemented
47
48 A valid ID number is a 5-digit integer matching the Parameter.idn_str_pattern
49 regular expression.
50 """
51 if Parameter.idn_str_pattern.match(i):
52 return int(i)
53 else:
54 return NotImplemented
55
57 """!Make sure input is a valid module number, otherwise return NotImplemented
58
59 A valid module number is an index counting from 0 at the front of the detector
60 up to NUM_MODULES-1
61 """
62 try:
63 m = int(m)
64 if m < 0 or m > Pattern.NUM_MODULES-1:
65 return NotImplemented
66 return m
67 except ValueError:
68 return NotImplemented
69
70 def __validate_layer(layer):
71 """!Make sure input is a valid layer number, otherwise return NotImplemented
72
73 A valid layer number is an index counting axial/stereo pairs from 1 at
74 the front of the detector up to NUM_MODULES
75 """
76 try:
77 layer = int(layer)
78 if layer < 1 or layer > Pattern.NUM_MODULES:
79 return NotImplemented
80 return layer
81 except ValueError:
82 return NotImplemented
83
84 # each one of these keywords (both binary and unary) are
85 # the names of functions in the Parameter class which return
86 # that value for the Parameter
87 binary_keywords = {
88 'id': __validate_id,
89 'module': __validate_module,
90 'layer': __validate_layer,
91 'direction': {'u': 1, 'v': 2, 'w': 3}
92 }
93 unary_keywords = [
94 'top',
95 'bottom',
96 'translation',
97 'rotation',
98 'individual',
99 'axial',
100 'stereo',
101 'front',
102 'back',
103 'hole',
104 'slot'
105 ]
106
107 # aliases are just a shortening of common Pattern strings
108 # that are drop-in replacements
109 aliases = {
110 'bot': 'bottom',
111 'trans': 'translation',
112 'rot': 'rotation',
113 'tu': 'direction=u & translation',
114 'rw': 'direction=w & rotation'
115 }
116
117 def _add_check(self, c):
118 """! add a check into our list of checks, making sure it is the correct format"""
119 if not isinstance(c, tuple) or len(c) != 2:
120 raise ValueError("Checks have to be 2-tuples")
121
122 kw = c[0].strip()
123
124 if kw in Pattern.binary_keywords.keys():
125 # check is a binary check
126 possible_values = Pattern.binary_keywords[kw]
127 val = c[1].strip()
128 if isinstance(possible_values, dict):
129 if val in possible_values.keys():
130 self._checks.append((kw, possible_values[val]))
131 else:
132 raise ValueError(f'Value {val} for {kw} not recognized. Possible values:\n{possible_values.keys()}')
133 else:
134 v = possible_values(val)
135 if v != NotImplemented:
136 self._checks.append((kw, v))
137 else:
138 raise ValueError(f'Value {val} for {kw} is not recognized.')
139 elif kw in Pattern.unary_keywords:
140 self._checks.append((kw, c[1]))
141 elif kw in Pattern.aliases:
142 self.__init__(Pattern.aliases[kw], first=False)
143 else:
144 raise ValueError(f'{kw} is not a recognized keyword')
145
146 def __init__(self, pattern, *, first=True):
147 if first:
148 self._checks = []
149 self._og_str = str(pattern)
150
151 if not isinstance(pattern, (int, str)):
152 raise ValueError(f'Pattern {pattern} must be an int or str')
153
154 # simplest pattern which is just the ID number
155 if isinstance(pattern, int) or pattern.isnumeric():
156 # make sure pattern is casted to str for the regex testing
157 self._add_check(('id', str(pattern)))
158 else:
159 # now complicated patterns
160 ops = pattern.split('&')
161 for op in ops:
162 if '=' in op:
163 # binary operation
164 split = op.split('=')
165 if len(split) != 2:
166 raise ValueError(f'{op} does not have two sides of the equality')
167 self._add_check(tuple(split))
168 else:
169 # unary operation
170 value = True
171 if op.startswith('!'):
172 op = op[1:]
173 value = False
174
175 self._add_check((op, value))
176
177 def match(self, p):
178 if not isinstance(p, Parameter):
179 return NotImplemented
180
181 for kw, val in self._checks:
182 if getattr(p, kw)() != val:
183 return False
184
185 return True
186
187 def __eq__(self, p):
188 return self.match(p)
189
190 def __repr__(self):
191 return self._og_str
Pattern that can match one or more paramters.
Definition _pattern.py:6
__validate_module(m)
Make sure input is a valid module number, otherwise return NotImplemented.
Definition _pattern.py:56
__validate_id(i)
Make sure input is a valid ID number, otherwise return NotImplemented.
Definition _pattern.py:45
__init__(self, pattern, *first=True)
Definition _pattern.py:146
_add_check(self, c)
add a check into our list of checks, making sure it is the correct format
Definition _pattern.py:117
__validate_layer(layer)
Make sure input is a valid layer number, otherwise return NotImplemented.
Definition _pattern.py:70