petal-qc 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of petal-qc might be problematic. Click here for more details.
- petal_qc/BTreport/CheckBTtests.py +321 -0
- petal_qc/BTreport/__init__.py +0 -0
- petal_qc/BTreport/bustapeReport.py +144 -0
- petal_qc/__init__.py +14 -0
- petal_qc/metrology/Cluster.py +90 -0
- petal_qc/metrology/DataFile.py +47 -0
- petal_qc/metrology/PetalMetrology.py +327 -0
- petal_qc/metrology/__init__.py +0 -0
- petal_qc/metrology/all2csv.py +57 -0
- petal_qc/metrology/analyze_locking_points.py +597 -0
- petal_qc/metrology/cold_noise.py +106 -0
- petal_qc/metrology/comparisonTable.py +59 -0
- petal_qc/metrology/convert_mitutoyo.py +175 -0
- petal_qc/metrology/convert_smartscope.py +145 -0
- petal_qc/metrology/coreMetrology.py +402 -0
- petal_qc/metrology/data2csv.py +63 -0
- petal_qc/metrology/do_Metrology.py +117 -0
- petal_qc/metrology/flatness4nigel.py +157 -0
- petal_qc/metrology/gtkutils.py +120 -0
- petal_qc/metrology/petal_flatness.py +353 -0
- petal_qc/metrology/show_data_file.py +118 -0
- petal_qc/metrology/testSummary.py +37 -0
- petal_qc/metrology/test_paralelism.py +71 -0
- petal_qc/thermal/CSVImage.py +69 -0
- petal_qc/thermal/DebugPlot.py +76 -0
- petal_qc/thermal/IRBFile.py +768 -0
- petal_qc/thermal/IRCore.py +110 -0
- petal_qc/thermal/IRDataGetter.py +359 -0
- petal_qc/thermal/IRPetal.py +1338 -0
- petal_qc/thermal/IRPetalParam.py +71 -0
- petal_qc/thermal/PetalColorMaps.py +62 -0
- petal_qc/thermal/Petal_IR_Analysis.py +142 -0
- petal_qc/thermal/PipeFit.py +598 -0
- petal_qc/thermal/__init__.py +0 -0
- petal_qc/thermal/analyze_IRCore.py +417 -0
- petal_qc/thermal/contours.py +378 -0
- petal_qc/thermal/create_IRCore.py +185 -0
- petal_qc/thermal/pipe_read.py +182 -0
- petal_qc/thermal/show_IR_petal.py +420 -0
- petal_qc/utils/Geometry.py +756 -0
- petal_qc/utils/Progress.py +182 -0
- petal_qc/utils/__init__.py +0 -0
- petal_qc/utils/all_files.py +35 -0
- petal_qc/utils/docx_utils.py +186 -0
- petal_qc/utils/fit_utils.py +188 -0
- petal_qc/utils/utils.py +180 -0
- petal_qc-0.0.0.dist-info/METADATA +29 -0
- petal_qc-0.0.0.dist-info/RECORD +51 -0
- petal_qc-0.0.0.dist-info/WHEEL +5 -0
- petal_qc-0.0.0.dist-info/entry_points.txt +3 -0
- petal_qc-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Thermal result of core."""
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from petal_qc.thermal import Petal_IR_Analysis
|
|
7
|
+
from petal_qc.thermal import IRPetalParam
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NumpyArrayEncoder(json.JSONEncoder):
|
|
11
|
+
"""Encoder to dump in JSon."""
|
|
12
|
+
|
|
13
|
+
def default(self, obj):
|
|
14
|
+
if isinstance(obj, np.integer):
|
|
15
|
+
return int(obj)
|
|
16
|
+
elif isinstance(obj, np.floating):
|
|
17
|
+
return float(obj)
|
|
18
|
+
elif isinstance(obj, np.ndarray):
|
|
19
|
+
return obj.tolist()
|
|
20
|
+
else:
|
|
21
|
+
return vars(obj)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class IRCore(object):
|
|
25
|
+
"""All the thermal data needed for one core."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, SN, alias="", results=None, params=None) -> None:
|
|
28
|
+
"""Initializarion.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
SN (str): Serial number of the core
|
|
32
|
+
alias (str): Alternative ID for the core
|
|
33
|
+
params (IRPetalParam): Parameters
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
self.coreID = SN
|
|
37
|
+
self.aliasID = alias
|
|
38
|
+
self.date = None
|
|
39
|
+
self.institute = params.institute if params is not None else None
|
|
40
|
+
self.params = params
|
|
41
|
+
self.files = []
|
|
42
|
+
self.results = [] if results is None else results # list of AnalysisResults. One per side
|
|
43
|
+
self.golden = [] # list of Golden results. One per side.
|
|
44
|
+
|
|
45
|
+
def set_files(self, files):
|
|
46
|
+
"""Set the input files."""
|
|
47
|
+
self.files = []
|
|
48
|
+
for F in files:
|
|
49
|
+
self.files.append(F)
|
|
50
|
+
|
|
51
|
+
print(self.files)
|
|
52
|
+
|
|
53
|
+
def set_results(self, results):
|
|
54
|
+
"""Set results.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
results (list): list of AnalysisResults
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
self.results = results
|
|
61
|
+
|
|
62
|
+
def add_file(self, fnam):
|
|
63
|
+
"""Add a new file path."""
|
|
64
|
+
self.files.append(fnam)
|
|
65
|
+
|
|
66
|
+
def to_json(self, pf=None):
|
|
67
|
+
"""Dumps to JSon."""
|
|
68
|
+
out = json.dumps(self, indent=3, cls=NumpyArrayEncoder)
|
|
69
|
+
if pf:
|
|
70
|
+
pf.write(out)
|
|
71
|
+
|
|
72
|
+
return out
|
|
73
|
+
|
|
74
|
+
def apply_deltaT(self, deltaT):
|
|
75
|
+
"""Applies a delta T correction."""
|
|
76
|
+
for i in range(2):
|
|
77
|
+
self.results[i].path_temp = np.array(self.results[i].path_temp) + deltaT
|
|
78
|
+
self.results[i].sensor_avg = np.array(self.results[i].sensor_avg) + deltaT
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def read_json(fnam):
|
|
82
|
+
"""Read a JSon file."""
|
|
83
|
+
js = None
|
|
84
|
+
with open(fnam, 'r', encoding='UTF-8') as ifp:
|
|
85
|
+
js = json.load(ifp)
|
|
86
|
+
|
|
87
|
+
return IRCore.from_json(js)
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def from_json(J):
|
|
91
|
+
"""Loads a JSon object."""
|
|
92
|
+
param = IRPetalParam.IRPetalParam(J["params"])
|
|
93
|
+
results = []
|
|
94
|
+
for o in J["results"]:
|
|
95
|
+
r = Petal_IR_Analysis.AnalysisResult()
|
|
96
|
+
r.from_json(o)
|
|
97
|
+
results.append(r)
|
|
98
|
+
|
|
99
|
+
C = IRCore(J["coreID"], J["aliasID"], results=results, params=param)
|
|
100
|
+
C.date = J["date"]
|
|
101
|
+
for F in J["files"]:
|
|
102
|
+
C.add_file(F)
|
|
103
|
+
|
|
104
|
+
return C
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
with open("core.json", "r", encoding="UTF-8") as ifp:
|
|
109
|
+
O = IRCore.from_json(json.load(ifp))
|
|
110
|
+
print(O)
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"""Encapsulates different data structure at DESY and IFIC.
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from petal_qc.thermal import IRPetal
|
|
7
|
+
from petal_qc.thermal import Petal_IR_Analysis
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class IRDataGetter(object):
|
|
11
|
+
"""BAse class defining the interface."""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
"""Initialization."""
|
|
15
|
+
self.factor = 1
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def factory(institute, params):
|
|
20
|
+
"""Returns the data getter corresponding to the given institute."""
|
|
21
|
+
if institute == "DESY":
|
|
22
|
+
out = IRDataDESY()
|
|
23
|
+
|
|
24
|
+
elif institute == "IFIC":
|
|
25
|
+
out = IRDataIFIC()
|
|
26
|
+
|
|
27
|
+
else:
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
out.fine_tune_params(params)
|
|
31
|
+
return out
|
|
32
|
+
|
|
33
|
+
def fine_tune_params(self, param):
|
|
34
|
+
"""Set default values for the parameters."""
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
def get_IR_data(self, image, **kargs):
|
|
38
|
+
"""_summary_
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
----
|
|
42
|
+
image (IRBImage): the input IRB image
|
|
43
|
+
kargs: keyword arguments to pass.
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def find_reference_image(self, irbf, *args, **kargs):
|
|
49
|
+
"""Find first image in sequence with T < T_min.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
----
|
|
53
|
+
irbf: The sequence of IR images
|
|
54
|
+
T_min: The temperature threshold
|
|
55
|
+
kargs (keyword arguments): keyword arguments
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
min_T, i_min, values: The actual temperature of the image,
|
|
60
|
+
the sequence nubmer
|
|
61
|
+
and the array of values (a 2d array)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
return 0, 0, []
|
|
66
|
+
|
|
67
|
+
def extract_pipe_path(self, image, params) -> list:
|
|
68
|
+
"""Extract the "pipe path" in a petal IR image.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
----
|
|
72
|
+
image (mdarray): The 2D array containing the input image
|
|
73
|
+
params: IRPetalPam object with options.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
pipe: the list of pipe contours or paths.
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
def analyze_IR_image(self, img, pipe, sensors, iside, params):
|
|
83
|
+
"""Analyze the IR image at input.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
----
|
|
87
|
+
img (IRBImage): THe image
|
|
88
|
+
pipes: The pipe
|
|
89
|
+
sensors: The sensor areas
|
|
90
|
+
iside: petal image with EoS on the left(0) or right (1)
|
|
91
|
+
params: IRPetal parameters
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
An array of AnalysisResult objects.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
def get_analysis_frame(self, irbf):
|
|
101
|
+
"""Get the frame where we want to perform the analysis."""
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class IRDataIFIC(IRDataGetter):
|
|
106
|
+
"""Gets data for IFIC analysis."""
|
|
107
|
+
|
|
108
|
+
def __init__(self) -> None:
|
|
109
|
+
"""Initialization."""
|
|
110
|
+
super().__init__()
|
|
111
|
+
|
|
112
|
+
def find_reference_image(self, irbf, *args, **kargs):
|
|
113
|
+
"""Find first image in sequence with T < T_min.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
----
|
|
117
|
+
irbf: The sequence of IR images
|
|
118
|
+
T_min: The temperature threshold
|
|
119
|
+
kargs (keyword arguments): keyword arguments
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
min_T, i_min, values: The actual temperature of the image,
|
|
124
|
+
the sequence nubmer
|
|
125
|
+
and the array of values (a 2d array)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
"""
|
|
129
|
+
if len(args) == 0:
|
|
130
|
+
T_min = -22.0
|
|
131
|
+
else:
|
|
132
|
+
T_min = args[0]
|
|
133
|
+
|
|
134
|
+
irbf.set_concatenate(True)
|
|
135
|
+
min_T, i_min, ref_img = IRPetal.find_reference_image(irbf, T_min)
|
|
136
|
+
values = self.get_IR_data(ref_img)
|
|
137
|
+
self.factor = values.shape[0]/640
|
|
138
|
+
|
|
139
|
+
return min_T, i_min, [values, ]
|
|
140
|
+
|
|
141
|
+
def get_IR_data(self, image, **kargs):
|
|
142
|
+
"""Get the data from the image in the proper orientation.
|
|
143
|
+
|
|
144
|
+
Proper orientation means that petals are vertical (in the mirror image).
|
|
145
|
+
It will eventually try to rotate the image to compensate a camera rotation.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
----
|
|
149
|
+
image: IRBimage. If a list of IRBFile objects is given, only the frist is taken.
|
|
150
|
+
rotate: True to make the rotation compensation.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
2d array: The 2d array wit the temperature data.
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
if isinstance(image, list) or isinstance(image, tuple):
|
|
158
|
+
image = image[0]
|
|
159
|
+
|
|
160
|
+
nrow, ncol = image.image.shape
|
|
161
|
+
landscape = (ncol > nrow)
|
|
162
|
+
|
|
163
|
+
if landscape:
|
|
164
|
+
values = image.image.T
|
|
165
|
+
else:
|
|
166
|
+
values = image.image
|
|
167
|
+
|
|
168
|
+
rotate = False
|
|
169
|
+
if 'rotate' in kargs:
|
|
170
|
+
rotate = kargs['rotate']
|
|
171
|
+
|
|
172
|
+
if rotate:
|
|
173
|
+
values = IRPetal.rotate_full_image(values)
|
|
174
|
+
|
|
175
|
+
return values
|
|
176
|
+
|
|
177
|
+
def extract_pipe_path(self, image, params) -> list:
|
|
178
|
+
"""Extract the "pipe path" in a petal IR image.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
----
|
|
182
|
+
image(ndarray): The 2D array containing the 2 specular images
|
|
183
|
+
params: IRPetalPam object with options.
|
|
184
|
+
|
|
185
|
+
Returns
|
|
186
|
+
-------
|
|
187
|
+
pipe: the list of pipe contours or paths.
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
pipes = IRPetal.extract_mirrored_pipe_path(image, params)
|
|
192
|
+
except Exception:
|
|
193
|
+
pipes = IRPetal.extract_mirrored_pipe_path(image[0], params)
|
|
194
|
+
return pipes
|
|
195
|
+
|
|
196
|
+
def analyze_IR_image(self, img, pipe, sensors, iside, params):
|
|
197
|
+
"""IFIC implementation.
|
|
198
|
+
|
|
199
|
+
Analyzes an image with specular images of petal core.
|
|
200
|
+
|
|
201
|
+
Inputs have same meaning as bas eclass but are arrays with the 2 core sides.
|
|
202
|
+
"""
|
|
203
|
+
res, _ = Petal_IR_Analysis.analyze_IR_mirrored_image(img, pipe, sensors, params)
|
|
204
|
+
return res
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def find_minimum(values):
|
|
208
|
+
"""Find minima in series."""
|
|
209
|
+
indx = []
|
|
210
|
+
|
|
211
|
+
for i, v in enumerate(values):
|
|
212
|
+
if i == 0:
|
|
213
|
+
vprev = v
|
|
214
|
+
continue
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
vnext = values[i+1]
|
|
218
|
+
except IndexError:
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
if vprev > v and vnext > v:
|
|
222
|
+
indx.append(i)
|
|
223
|
+
|
|
224
|
+
vprev = v
|
|
225
|
+
|
|
226
|
+
return indx
|
|
227
|
+
|
|
228
|
+
def get_analysis_frame(self, irbf):
|
|
229
|
+
"""Get the frame where we want to perform the analysis.
|
|
230
|
+
|
|
231
|
+
IFIC takes the minimum of the last cycle.
|
|
232
|
+
"""
|
|
233
|
+
# Get all the temperatures
|
|
234
|
+
min_T = []
|
|
235
|
+
for img in irbf.images():
|
|
236
|
+
min_T.append(np.min(img[0].image))
|
|
237
|
+
|
|
238
|
+
indx = IRDataIFIC.find_minimum(min_T)
|
|
239
|
+
return [irbf.getImage(indx[-1])]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class IRDataDESY(IRDataGetter):
|
|
243
|
+
"""Gets data for DESY."""
|
|
244
|
+
|
|
245
|
+
def __init__(self) -> None:
|
|
246
|
+
"""Initialization."""
|
|
247
|
+
super().__init__()
|
|
248
|
+
|
|
249
|
+
def fine_tune_params(self, param):
|
|
250
|
+
"""Set default values for the parameters."""
|
|
251
|
+
param.distance = 16
|
|
252
|
+
param.width = 16
|
|
253
|
+
|
|
254
|
+
def get_IR_data(self, image, **kargs):
|
|
255
|
+
"""Get the data from the image in the proper orientation.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
----
|
|
259
|
+
image: IRBimage
|
|
260
|
+
kargs: keyword arguments
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
2d array: The 2d array wit the temperature data.
|
|
265
|
+
|
|
266
|
+
"""
|
|
267
|
+
try:
|
|
268
|
+
values = np.rot90(image.image)
|
|
269
|
+
except Exception:
|
|
270
|
+
values = []
|
|
271
|
+
for img in image:
|
|
272
|
+
values.append(np.rot90(img.image))
|
|
273
|
+
|
|
274
|
+
return values
|
|
275
|
+
|
|
276
|
+
def find_reference_image(self, irbf, *args, **kargs):
|
|
277
|
+
"""DESY wants the average of all images in the sequence.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
----
|
|
281
|
+
irbf: The sequence of IR images
|
|
282
|
+
args: The temperature threshold
|
|
283
|
+
kargs (keyword arguments): keyword arguments
|
|
284
|
+
|
|
285
|
+
Returns
|
|
286
|
+
-------
|
|
287
|
+
min_T, i_min, values: The actual temperature of the image,
|
|
288
|
+
the sequence nubmer
|
|
289
|
+
and the array of values (a 2d array)
|
|
290
|
+
|
|
291
|
+
"""
|
|
292
|
+
if 'nframes' in kargs:
|
|
293
|
+
nframes = kargs['nframes']
|
|
294
|
+
else:
|
|
295
|
+
nframes = -1
|
|
296
|
+
|
|
297
|
+
min_T = 1e50
|
|
298
|
+
avg_img = irbf.append_average(nframes=nframes)
|
|
299
|
+
for img in avg_img:
|
|
300
|
+
val = np.min(img.image)
|
|
301
|
+
if val < min_T:
|
|
302
|
+
min_T = val
|
|
303
|
+
|
|
304
|
+
i_min = irbf.nimages-1
|
|
305
|
+
values = self.get_IR_data(avg_img)
|
|
306
|
+
|
|
307
|
+
factors = []
|
|
308
|
+
for img in values:
|
|
309
|
+
factors.append(img.shape[0]/640)
|
|
310
|
+
self.factor = max(factors)
|
|
311
|
+
|
|
312
|
+
return min_T, i_min, values
|
|
313
|
+
|
|
314
|
+
def extract_pipe_path(self, images, params) -> list:
|
|
315
|
+
"""Extract the "pipe path" in a petal IR image.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
----
|
|
319
|
+
images(list(ndarray)): The array of 2D arrays containing the images
|
|
320
|
+
params: IRPetalPam object with options.
|
|
321
|
+
|
|
322
|
+
Returns
|
|
323
|
+
-------
|
|
324
|
+
pipe: the list of pipe contours or paths.
|
|
325
|
+
|
|
326
|
+
"""
|
|
327
|
+
pipes = []
|
|
328
|
+
for img in images:
|
|
329
|
+
pipe = IRPetal.extract_pipe_path(img, params)
|
|
330
|
+
pipes.append(pipe)
|
|
331
|
+
|
|
332
|
+
IRPetal.set_images(images)
|
|
333
|
+
return pipes
|
|
334
|
+
|
|
335
|
+
def analyze_IR_image(self, img, pipes, sensors, iside, params):
|
|
336
|
+
"""DESY implementation.
|
|
337
|
+
|
|
338
|
+
Only one petal side at imput.
|
|
339
|
+
"""
|
|
340
|
+
if isinstance(img, list):
|
|
341
|
+
res = Petal_IR_Analysis.analyze_IR_image_list(img, pipes, sensors, params)
|
|
342
|
+
return res
|
|
343
|
+
|
|
344
|
+
else:
|
|
345
|
+
res = Petal_IR_Analysis.analyze_IR_image(img, pipes[0], sensors[0], iside[0], params)
|
|
346
|
+
if iside[0]:
|
|
347
|
+
return [None, res]
|
|
348
|
+
else:
|
|
349
|
+
return [res, None]
|
|
350
|
+
|
|
351
|
+
def get_analysis_frame(self, irbf):
|
|
352
|
+
"""Get the frame where we want to perform the analysis.
|
|
353
|
+
|
|
354
|
+
DESY gets the average of all frames.
|
|
355
|
+
"""
|
|
356
|
+
if not irbf.has_average:
|
|
357
|
+
irbf.append_average(nframes=5)
|
|
358
|
+
|
|
359
|
+
return [v[-1] for v in irbf.file_images]
|