petal-qc 0.0.9__py3-none-any.whl → 0.0.11__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 +2 -6
- petal_qc/__init__.py +17 -1
- petal_qc/metrology/PetalMetrology.py +0 -5
- petal_qc/metrology/compare_Cores.py +27 -15
- petal_qc/metrology/coreMetrology.py +20 -10
- petal_qc/metrology/do_Metrology.py +0 -5
- petal_qc/metrology/petal_flatness.py +0 -4
- petal_qc/metrology/readAVSdata.py +762 -0
- petal_qc/metrology/uploadPetalInformation.py +769 -0
- petal_qc/test/checkAVStests.py +181 -0
- petal_qc/test/compare_golden.py +44 -0
- petal_qc/test/getAVSjson.py +27 -0
- petal_qc/test/getAVStests.py +263 -0
- petal_qc/test/getPetalCoreTestSummary.py +89 -0
- petal_qc/test/listPetalCoreComponents.py +89 -0
- petal_qc/test/prepareDESYfiles.py +25 -8
- petal_qc/thermal/DESYdata.py +58 -0
- petal_qc/thermal/IRBFile.py +51 -7
- petal_qc/thermal/IRCore.py +1 -1
- petal_qc/thermal/IRDataGetter.py +43 -24
- petal_qc/thermal/IRPetal.py +84 -7
- petal_qc/thermal/IRPetalParam.py +1 -1
- petal_qc/thermal/Petal_IR_Analysis.py +4 -3
- petal_qc/thermal/PipeFit.py +12 -3
- petal_qc/thermal/analyze_IRCore.py +24 -15
- petal_qc/thermal/coreThermal.py +124 -28
- petal_qc/thermal/create_IRCore.py +35 -9
- petal_qc/thermal/create_core_report.py +31 -8
- petal_qc/utils/Geometry.py +2 -2
- petal_qc/utils/readGraphana.py +2 -1
- {petal_qc-0.0.9.dist-info → petal_qc-0.0.11.dist-info}/METADATA +2 -2
- petal_qc-0.0.11.dist-info/RECORD +70 -0
- {petal_qc-0.0.9.dist-info → petal_qc-0.0.11.dist-info}/WHEEL +1 -1
- {petal_qc-0.0.9.dist-info → petal_qc-0.0.11.dist-info}/entry_points.txt +3 -0
- petal_qc-0.0.9.dist-info/RECORD +0 -61
- {petal_qc-0.0.9.dist-info → petal_qc-0.0.11.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""Prepare raw data input files from DESY so that we can use them with this code."""
|
|
3
3
|
import os
|
|
4
4
|
import fnmatch
|
|
5
5
|
import re
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
import argparse
|
|
7
8
|
|
|
8
9
|
def all_files(root, patterns='*', single_level=False, yield_folders=False):
|
|
9
10
|
"""A generator that reruns all files in the given folder.
|
|
@@ -41,18 +42,26 @@ class PetalCore:
|
|
|
41
42
|
self.back = {}
|
|
42
43
|
|
|
43
44
|
def main(folder, out_folder):
|
|
44
|
-
"""Main entry point.
|
|
45
|
+
"""Main entry point.
|
|
46
|
+
|
|
47
|
+
It takes DESY raw data files and combines them into a single file for front
|
|
48
|
+
and back metrology.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
folder: the input folder where to find the original files.
|
|
52
|
+
out_folder: the folder where the new fiels will be stored.
|
|
53
|
+
"""
|
|
45
54
|
outF = Path(out_folder).expanduser().resolve()
|
|
46
55
|
if not outF.exists():
|
|
47
56
|
os.mkdir(outF)
|
|
48
|
-
|
|
49
|
-
rgx = re.compile(r"Project Name: (\w+)side_.*AlternativeID=PPC-(\d+)", re.MULTILINE|re.DOTALL)
|
|
57
|
+
|
|
58
|
+
rgx = re.compile(r"Project Name: (\w+)side_.*AlternativeID=PPC[-_](\d+)", re.MULTILINE|re.DOTALL)
|
|
50
59
|
petal_cores = {}
|
|
51
60
|
for fnam in all_files(folder, "*.txt"):
|
|
52
61
|
P = Path(fnam).expanduser().resolve()
|
|
53
62
|
with open(fnam, "r", encoding="UTF-8") as ff:
|
|
54
63
|
R = rgx.search(ff.read())
|
|
55
|
-
if R:
|
|
64
|
+
if R:
|
|
56
65
|
petal_id = "PPC.{}".format(R.group(2))
|
|
57
66
|
side = R.group(1).lower()
|
|
58
67
|
if "_2D_" in P.name:
|
|
@@ -75,12 +84,20 @@ def main(folder, out_folder):
|
|
|
75
84
|
list_file.write("{} {}-{} {}\n".format(oname, petal_id, side, petal_id))
|
|
76
85
|
data = ""
|
|
77
86
|
for data_type, fnam in values.items():
|
|
87
|
+
if fnam is None:
|
|
88
|
+
print("This should not happen.")
|
|
89
|
+
|
|
78
90
|
with open(fnam, "r", encoding="UTF-8") as ifile:
|
|
79
91
|
data += ifile.read()
|
|
80
|
-
|
|
92
|
+
|
|
81
93
|
with open(oname, "w", encoding="UTF-8") as ofile:
|
|
82
94
|
ofile.write(data)
|
|
83
|
-
|
|
95
|
+
|
|
84
96
|
list_file.close()
|
|
97
|
+
|
|
85
98
|
if __name__ == "__main__":
|
|
86
|
-
|
|
99
|
+
parser = argparse.ArgumentParser()
|
|
100
|
+
parser.add_argument("--input-folder", default=None, help="Input folder")
|
|
101
|
+
parser.add_argument("--output-folder", help="Outout fodler", default=None)
|
|
102
|
+
|
|
103
|
+
main("/Users/lacasta/Downloads/Report_QC-desy_Sep2024", "/tmp/desy")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Dialog to get DESY IRB files."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import itkdb_gtk
|
|
4
|
+
import itkdb_gtk.dbGtkUtils
|
|
5
|
+
|
|
6
|
+
import gi
|
|
7
|
+
gi.require_version("Gtk", "3.0")
|
|
8
|
+
from gi.repository import Gtk, Gio
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DesyData(Gtk.Dialog):
|
|
12
|
+
"""To get DESY data"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, files=None):
|
|
15
|
+
super().__init__(title="DESY IRB files")
|
|
16
|
+
|
|
17
|
+
self.front = None
|
|
18
|
+
self.back = None
|
|
19
|
+
|
|
20
|
+
self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
|
21
|
+
Gtk.STOCK_OK, Gtk.ResponseType.OK)
|
|
22
|
+
|
|
23
|
+
area = self.get_content_area()
|
|
24
|
+
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
|
25
|
+
area.pack_start(box, True, True, 10)
|
|
26
|
+
|
|
27
|
+
lbl = Gtk.Label(label="Choose the IRB files.")
|
|
28
|
+
box.pack_start(lbl, True, True, 10)
|
|
29
|
+
|
|
30
|
+
grid = Gtk.Grid(column_spacing=10, row_spacing=5)
|
|
31
|
+
box.pack_start(grid, True, True, 10)
|
|
32
|
+
grid.attach(Gtk.Label(label="Front"), 0, 0, 1, 1)
|
|
33
|
+
grid.attach(Gtk.Label(label="Back"), 0, 1, 1, 1)
|
|
34
|
+
|
|
35
|
+
fback = Gtk.FileChooserButton()
|
|
36
|
+
fback.connect("file-set", self.on_file_set, 0)
|
|
37
|
+
ffront = Gtk.FileChooserButton()
|
|
38
|
+
ffront.connect("file-set", self.on_file_set, 1)
|
|
39
|
+
grid.attach(ffront, 1, 0, 1, 1)
|
|
40
|
+
grid.attach(fback, 1, 1, 1, 1)
|
|
41
|
+
|
|
42
|
+
if files is not None and len(files)==2:
|
|
43
|
+
ffront.set_file(Gio.File.new_for_path(files[0]))
|
|
44
|
+
fback.set_file(Gio.File.new_for_path(files[1]))
|
|
45
|
+
|
|
46
|
+
def on_file_set(self, *args):
|
|
47
|
+
"""Get back side file."""
|
|
48
|
+
fnam = args[0].get_filename()
|
|
49
|
+
if fnam is None or not Path(fnam).exists():
|
|
50
|
+
itkdb_gtk.dbGtkUtils.complain("Could not find Data File", fnam, parent=self)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
if args[1] == 0:
|
|
54
|
+
self.back = fnam
|
|
55
|
+
elif args[1] == 1:
|
|
56
|
+
self.front = fnam
|
|
57
|
+
else:
|
|
58
|
+
itkdb_gtk.dbGtkUtils.complain("This should not happen.", fnam, parent=self)
|
petal_qc/thermal/IRBFile.py
CHANGED
|
@@ -166,11 +166,32 @@ class HeaderBlock(object):
|
|
|
166
166
|
self.word8 = ifile.getInt()
|
|
167
167
|
self.end = ifile.tell()
|
|
168
168
|
|
|
169
|
+
if self.end - self.where != 32:
|
|
170
|
+
raise RuntimeError("byte counting error in parsing of HeaderBlock")
|
|
171
|
+
|
|
169
172
|
def get_name(self):
|
|
170
173
|
"""Return the header type as string."""
|
|
171
174
|
return HeaderBlock.header_name[self.type]
|
|
172
175
|
|
|
173
176
|
|
|
177
|
+
class IRBPreview(object):
|
|
178
|
+
"""A preview in the IRB file."""
|
|
179
|
+
|
|
180
|
+
def __init__(self, block):
|
|
181
|
+
"""Initialize.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
block: the block with the information.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
self.block = block
|
|
188
|
+
old_position = block.ifile.tell()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
block.ifile.seek(old_position)
|
|
193
|
+
|
|
194
|
+
|
|
174
195
|
class IRBImage(object):
|
|
175
196
|
"""An image in the IRBis file."""
|
|
176
197
|
|
|
@@ -181,7 +202,6 @@ class IRBImage(object):
|
|
|
181
202
|
"""Initialize.
|
|
182
203
|
|
|
183
204
|
Args:
|
|
184
|
-
----
|
|
185
205
|
ifile: The input file
|
|
186
206
|
block: The block with the information.
|
|
187
207
|
|
|
@@ -233,9 +253,8 @@ class IRBImage(object):
|
|
|
233
253
|
zero = ifile.getShort()
|
|
234
254
|
|
|
235
255
|
if self.width > 10000 or self.height > 10000:
|
|
236
|
-
|
|
256
|
+
raise RuntimeError("Image size out of range ({}x{})".format(
|
|
237
257
|
self.width, self.height))
|
|
238
|
-
return
|
|
239
258
|
|
|
240
259
|
flagsPosition = block.offset + IRBImage.FLAGS_OFFSET
|
|
241
260
|
self.readImageFlags(flagsPosition)
|
|
@@ -314,13 +333,18 @@ class IRBImage(object):
|
|
|
314
333
|
if v2_count < 1:
|
|
315
334
|
v2_count = v2_data[v2_pos]
|
|
316
335
|
v2 = v2_data[v2_pos+1]
|
|
317
|
-
|
|
336
|
+
if v2 < 0:
|
|
337
|
+
v2 += 256
|
|
338
|
+
P1 = self.palette[(v2+1) % 256]
|
|
318
339
|
P2 = self.palette[v2]
|
|
319
340
|
v2_pos += 2
|
|
320
341
|
|
|
321
342
|
v2_count -= 1
|
|
322
343
|
|
|
323
344
|
v1 = v1_data[i]
|
|
345
|
+
if v1 < 0:
|
|
346
|
+
v1 += 256
|
|
347
|
+
|
|
324
348
|
f = v1/256.0
|
|
325
349
|
|
|
326
350
|
# linear interpolation betweeen eighboring palette entries
|
|
@@ -423,6 +447,7 @@ class IRBFile(object):
|
|
|
423
447
|
"""
|
|
424
448
|
self.concatenate = concatenate
|
|
425
449
|
self.imgList = []
|
|
450
|
+
self.previewList = []
|
|
426
451
|
self.blocks = []
|
|
427
452
|
self.ifiles = []
|
|
428
453
|
self.file_images = []
|
|
@@ -493,6 +518,9 @@ class IRBFile(object):
|
|
|
493
518
|
if block.type == HeaderBlock.IMAGE:
|
|
494
519
|
image = IRBImage(block)
|
|
495
520
|
self.imgList.append(image)
|
|
521
|
+
elif block.type == HeaderBlock.PREVIEW:
|
|
522
|
+
image = IRBPreview(block)
|
|
523
|
+
self.previewList.append(image)
|
|
496
524
|
|
|
497
525
|
if self.is_sequence:
|
|
498
526
|
offset = -1
|
|
@@ -549,6 +577,10 @@ class IRBFile(object):
|
|
|
549
577
|
self.current_file = i
|
|
550
578
|
self.imgList = self.file_images[i]
|
|
551
579
|
|
|
580
|
+
def getImage_timestamp(self, i):
|
|
581
|
+
"""Return timestamp of i-th image."""
|
|
582
|
+
return self.imgList[i].timestamp
|
|
583
|
+
|
|
552
584
|
def getImage(self, i):
|
|
553
585
|
"""Get i-th image in current file.
|
|
554
586
|
|
|
@@ -682,7 +714,7 @@ class IRBFile(object):
|
|
|
682
714
|
return out
|
|
683
715
|
|
|
684
716
|
|
|
685
|
-
def open_file(fname):
|
|
717
|
+
def open_file(fname, concat=False):
|
|
686
718
|
"""Opens a file an returns a IRBFile instance.
|
|
687
719
|
|
|
688
720
|
Args:
|
|
@@ -694,7 +726,19 @@ def open_file(fname):
|
|
|
694
726
|
if is_iterable(fname):
|
|
695
727
|
# we assume it is a list of IRB files...
|
|
696
728
|
try:
|
|
697
|
-
|
|
729
|
+
if concat:
|
|
730
|
+
irbf = IRBFile(fname)
|
|
731
|
+
return irbf
|
|
732
|
+
else:
|
|
733
|
+
out = []
|
|
734
|
+
for f in fname:
|
|
735
|
+
irbf = IRBFile(f)
|
|
736
|
+
out.append(irbf)
|
|
737
|
+
|
|
738
|
+
if len(out) == 1:
|
|
739
|
+
out = out[0]
|
|
740
|
+
|
|
741
|
+
return out
|
|
698
742
|
|
|
699
743
|
except FileNotFoundError as eee:
|
|
700
744
|
print(eee)
|
|
@@ -769,4 +813,4 @@ def main():
|
|
|
769
813
|
plt.show()
|
|
770
814
|
|
|
771
815
|
if __name__ == "__main__":
|
|
772
|
-
main()
|
|
816
|
+
main()
|
petal_qc/thermal/IRCore.py
CHANGED
|
@@ -41,7 +41,7 @@ class IRCore(object):
|
|
|
41
41
|
self.files = []
|
|
42
42
|
self.results = [] if results is None else results # list of AnalysisResults. One per side
|
|
43
43
|
self.golden = [] # list of Golden results. One per side.
|
|
44
|
-
self.inlet =
|
|
44
|
+
self.inlet = params.tco2
|
|
45
45
|
|
|
46
46
|
def set_files(self, files):
|
|
47
47
|
"""Set the input files."""
|
petal_qc/thermal/IRDataGetter.py
CHANGED
|
@@ -19,10 +19,10 @@ HAS_GRAPHANA = False
|
|
|
19
19
|
try:
|
|
20
20
|
from petal_qc.utils.readGraphana import ReadGraphana
|
|
21
21
|
HAS_GRAPHANA = True
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
except ImportError:
|
|
24
24
|
HAS_GRAPHANA = False
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class IRDataGetter(object):
|
|
@@ -62,7 +62,7 @@ class IRDataGetter(object):
|
|
|
62
62
|
kargs: keyword arguments to pass.
|
|
63
63
|
|
|
64
64
|
"""
|
|
65
|
-
|
|
65
|
+
return
|
|
66
66
|
|
|
67
67
|
def find_reference_image(self, irbf, *args, **kargs):
|
|
68
68
|
"""Find first image in sequence with T < T_min.
|
|
@@ -114,7 +114,7 @@ class IRDataGetter(object):
|
|
|
114
114
|
An array of AnalysisResult objects.
|
|
115
115
|
|
|
116
116
|
"""
|
|
117
|
-
|
|
117
|
+
return
|
|
118
118
|
|
|
119
119
|
def get_analysis_frame(self, irbf):
|
|
120
120
|
"""Get the frame where we want to perform the analysis."""
|
|
@@ -166,12 +166,12 @@ class IRDataIFIC(IRDataGetter):
|
|
|
166
166
|
# T_min = -22.0
|
|
167
167
|
# else:
|
|
168
168
|
# T_min = args[0]
|
|
169
|
-
#
|
|
169
|
+
#
|
|
170
170
|
# irbf.set_concatenate(True)
|
|
171
171
|
# min_T, i_min, ref_img = IRPetal.find_reference_image(irbf, T_min)
|
|
172
172
|
# values = self.get_IR_data(ref_img)
|
|
173
173
|
# self.factor = values.shape[0]/640
|
|
174
|
-
#
|
|
174
|
+
#
|
|
175
175
|
# return min_T, i_min, [values, ]
|
|
176
176
|
|
|
177
177
|
def get_IR_data(self, image, **kargs):
|
|
@@ -281,10 +281,10 @@ class IRDataIFIC(IRDataGetter):
|
|
|
281
281
|
img = self.analysis_frame[0]
|
|
282
282
|
X, T = self.DB.get_temperature(img.timestamp, 1)
|
|
283
283
|
return np.min(T)
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
else:
|
|
286
286
|
return -9999
|
|
287
|
-
|
|
287
|
+
|
|
288
288
|
|
|
289
289
|
|
|
290
290
|
class IRDataDESY(IRDataGetter):
|
|
@@ -343,14 +343,28 @@ class IRDataDESY(IRDataGetter):
|
|
|
343
343
|
nframes = -1
|
|
344
344
|
|
|
345
345
|
min_T = 1e50
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
346
|
+
i_min = -1
|
|
347
|
+
try:
|
|
348
|
+
avg_img = irbf.append_average(nframes=nframes)
|
|
349
|
+
for img in avg_img:
|
|
350
|
+
val = np.min(img.image)
|
|
351
|
+
if val < min_T:
|
|
352
|
+
min_T = val
|
|
351
353
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
+
i_min = irbf.nimages-1
|
|
355
|
+
values = self.get_IR_data(avg_img)
|
|
356
|
+
|
|
357
|
+
except AttributeError:
|
|
358
|
+
# We have 2 files, one front y the second back
|
|
359
|
+
values = []
|
|
360
|
+
factors = []
|
|
361
|
+
for ifile in irbf:
|
|
362
|
+
val = self.get_IR_data(ifile.getImage(0))
|
|
363
|
+
Tmin = np.min(val)
|
|
364
|
+
if Tmin < min_T:
|
|
365
|
+
min_T = Tmin
|
|
366
|
+
i_min = 0
|
|
367
|
+
values.append(val)
|
|
354
368
|
|
|
355
369
|
factors = []
|
|
356
370
|
for img in values:
|
|
@@ -359,25 +373,26 @@ class IRDataDESY(IRDataGetter):
|
|
|
359
373
|
|
|
360
374
|
return min_T, i_min, values
|
|
361
375
|
|
|
362
|
-
def extract_pipe_path(self,
|
|
376
|
+
def extract_pipe_path(self, image, params) -> list:
|
|
363
377
|
"""Extract the "pipe path" in a petal IR image.
|
|
364
378
|
|
|
365
379
|
Args:
|
|
366
|
-
|
|
367
|
-
images(list(ndarray)): The array of 2D arrays containing the images
|
|
380
|
+
image(list(ndarray)): The array of 2D arrays containing the images
|
|
368
381
|
params: IRPetalPam object with options.
|
|
369
382
|
|
|
370
383
|
Returns
|
|
371
|
-
-------
|
|
372
384
|
pipe: the list of pipe contours or paths.
|
|
373
385
|
|
|
374
386
|
"""
|
|
375
387
|
pipes = []
|
|
376
|
-
|
|
388
|
+
points_3d = []
|
|
389
|
+
for img in image:
|
|
377
390
|
pipe = IRPetal.extract_pipe_path(img, params)
|
|
391
|
+
points_3d.append(IRPetal.get_all_3d_points())
|
|
378
392
|
pipes.append(pipe)
|
|
379
393
|
|
|
380
|
-
IRPetal.
|
|
394
|
+
IRPetal.set_all_3d_points(points_3d)
|
|
395
|
+
IRPetal.set_images(image)
|
|
381
396
|
return pipes
|
|
382
397
|
|
|
383
398
|
def analyze_IR_image(self, img, pipes, sensors, iside, params):
|
|
@@ -401,7 +416,11 @@ class IRDataDESY(IRDataGetter):
|
|
|
401
416
|
|
|
402
417
|
DESY gets the average of all frames.
|
|
403
418
|
"""
|
|
404
|
-
|
|
405
|
-
irbf.
|
|
419
|
+
try:
|
|
420
|
+
if not irbf.has_average:
|
|
421
|
+
irbf.append_average(nframes=5)
|
|
422
|
+
|
|
423
|
+
return [v[-1] for v in irbf.file_images]
|
|
406
424
|
|
|
407
|
-
|
|
425
|
+
except AttributeError:
|
|
426
|
+
return [irbf[0].getImage(0), irbf[1].getImage(0)]
|
petal_qc/thermal/IRPetal.py
CHANGED
|
@@ -35,7 +35,7 @@ debug_plot = DebugPlot.DebugPlot()
|
|
|
35
35
|
the_segments = None # global variable to store the last segments found.
|
|
36
36
|
the_contours = None # Global variable to store the last contours found
|
|
37
37
|
the_images = None
|
|
38
|
-
|
|
38
|
+
the_3d_points = None
|
|
39
39
|
|
|
40
40
|
class DebugTempProfile(object):
|
|
41
41
|
"""Stores Debug data."""
|
|
@@ -68,6 +68,16 @@ class DebugTempProfile(object):
|
|
|
68
68
|
T_profile = None # Global to store the temp. profile.
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
def get_all_3d_points():
|
|
72
|
+
"""Return all pipe path 3D points."""
|
|
73
|
+
return the_3d_points
|
|
74
|
+
|
|
75
|
+
def set_all_3d_points(all_3d_points):
|
|
76
|
+
"""Set all pipe path 3D points."""
|
|
77
|
+
global the_3d_points
|
|
78
|
+
the_3d_points = all_3d_points
|
|
79
|
+
|
|
80
|
+
|
|
71
81
|
def get_last_segments():
|
|
72
82
|
"""Return the last segments found."""
|
|
73
83
|
global the_segments
|
|
@@ -145,6 +155,39 @@ class Segment(object):
|
|
|
145
155
|
|
|
146
156
|
return points
|
|
147
157
|
|
|
158
|
+
@staticmethod
|
|
159
|
+
def get_3d_points_in_list(segments):
|
|
160
|
+
"""Return a list with all the 3D points (x,y,T) in the list of segments.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
----
|
|
164
|
+
segments (list[Segment]): The list of segments
|
|
165
|
+
|
|
166
|
+
Returns
|
|
167
|
+
-------
|
|
168
|
+
np.array: array of points.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
# Count the number of points
|
|
172
|
+
npts = 0
|
|
173
|
+
for S in segments:
|
|
174
|
+
if S.Pmin is not None:
|
|
175
|
+
npts += len(S.Pmin)
|
|
176
|
+
|
|
177
|
+
points = np.zeros([npts, 3])
|
|
178
|
+
ipoint = 0
|
|
179
|
+
for S in segments:
|
|
180
|
+
if S.Pmin is None:
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
for i, Pmin in enumerate(S.Pmin):
|
|
184
|
+
points[ipoint, 0] = Pmin.x
|
|
185
|
+
points[ipoint, 1] = Pmin.y
|
|
186
|
+
points[ipoint, 2] = S.Tmin[i]
|
|
187
|
+
ipoint += 1
|
|
188
|
+
|
|
189
|
+
return points
|
|
190
|
+
|
|
148
191
|
@staticmethod
|
|
149
192
|
def get_spread_in_list(segments):
|
|
150
193
|
"""Return an array with spread values."""
|
|
@@ -323,7 +366,7 @@ def extract_mirrored_pipe_path(values, params):
|
|
|
323
366
|
(left_pipe, right_pipe): The 2 paths.
|
|
324
367
|
|
|
325
368
|
"""
|
|
326
|
-
global the_images
|
|
369
|
+
global the_images, the_3d_points
|
|
327
370
|
if params.rotate:
|
|
328
371
|
rotated = rotate_full_image(values)
|
|
329
372
|
else:
|
|
@@ -331,11 +374,14 @@ def extract_mirrored_pipe_path(values, params):
|
|
|
331
374
|
|
|
332
375
|
imgs = split_IR_image(rotated)
|
|
333
376
|
pipes = []
|
|
377
|
+
points_3d = []
|
|
334
378
|
for img in imgs:
|
|
335
379
|
pipe = extract_pipe_path(img, params)
|
|
336
380
|
pipes.append(pipe)
|
|
381
|
+
points_3d.append(get_all_3d_points())
|
|
337
382
|
|
|
338
383
|
the_images = imgs
|
|
384
|
+
the_3d_points = points_3d
|
|
339
385
|
return list(pipes)
|
|
340
386
|
|
|
341
387
|
|
|
@@ -684,7 +730,7 @@ def get_derivatives(T_min, x_min, x_max, coeff):
|
|
|
684
730
|
return valid_roots, valid_values, valid_curv
|
|
685
731
|
|
|
686
732
|
|
|
687
|
-
def show_profile(debug_plot):
|
|
733
|
+
def show_profile(debug_plot, title=None):
|
|
688
734
|
"""Plot a profile."""
|
|
689
735
|
debug_plot.setup_debug("Slices", is_3d=True)
|
|
690
736
|
if T_profile:
|
|
@@ -693,6 +739,12 @@ def show_profile(debug_plot):
|
|
|
693
739
|
if T_profile._pF is not None:
|
|
694
740
|
debug_plot.plotx("Slices", T_profile._pF[:, 0], T_profile._pF[:, 1], T_profile._Fn, 'b-')
|
|
695
741
|
|
|
742
|
+
if title:
|
|
743
|
+
debug_plot.set_title("Slices", title)
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
__call_id__ = 0
|
|
747
|
+
__img_num__ = 0
|
|
696
748
|
|
|
697
749
|
def slice_contours(data, inner, outer, distance=50, npoints=15, do_fit=False, show=False) -> list[Segment]:
|
|
698
750
|
"""Make slices between contours.
|
|
@@ -712,8 +764,11 @@ def slice_contours(data, inner, outer, distance=50, npoints=15, do_fit=False, sh
|
|
|
712
764
|
A list of Segments.
|
|
713
765
|
|
|
714
766
|
"""
|
|
715
|
-
global debug_plot
|
|
767
|
+
global debug_plot, __call_id__, __img_num__
|
|
716
768
|
|
|
769
|
+
__call_id__ += 1
|
|
770
|
+
__img_num__ = 0
|
|
771
|
+
#show=True
|
|
717
772
|
segments = []
|
|
718
773
|
dist = 0
|
|
719
774
|
npts = len(outer)
|
|
@@ -726,7 +781,15 @@ def slice_contours(data, inner, outer, distance=50, npoints=15, do_fit=False, sh
|
|
|
726
781
|
U = contours.find_closest(x0, y0, inner)
|
|
727
782
|
Tmin, Pmin, spread = get_T_profile(data, Point(x0, y0), Point(U[0], U[1]), npts=npoints, do_fit=do_fit, debug=False)
|
|
728
783
|
if show:
|
|
729
|
-
show_profile(debug_plot)
|
|
784
|
+
show_profile(debug_plot, "Dist {:.3f}, Tmin {:.2f} ({:.1f}, {:.1f})".format(dist, Tmin[0], Pmin[0].x, Pmin[0].y))
|
|
785
|
+
debug_plot.savefig("Slices", "/tmp/img_{}_{}.png".format(__call_id__, __img_num__))
|
|
786
|
+
__img_num__ += 1
|
|
787
|
+
try:
|
|
788
|
+
ax = debug_plot.get_ax("Contours")
|
|
789
|
+
ax.plot([x0, U[0]], [y0, U[1]], '-')
|
|
790
|
+
ax.plot(Pmin[0].x, Pmin[0].y, 'o')
|
|
791
|
+
except KeyError:
|
|
792
|
+
pass
|
|
730
793
|
|
|
731
794
|
# store results: distance along segment and temperature
|
|
732
795
|
T = []
|
|
@@ -764,7 +827,16 @@ def slice_contours(data, inner, outer, distance=50, npoints=15, do_fit=False, sh
|
|
|
764
827
|
|
|
765
828
|
segments.append(Segment((x0, y0), V, Pmin, path_length, Tmin, spread))
|
|
766
829
|
if show:
|
|
767
|
-
show_profile(debug_plot)
|
|
830
|
+
show_profile(debug_plot, "Dist {:.3f} Tmin {:.2f} ({:.1f}, {:.1f})".format(path_length, Tmin[0], Pmin[0].x, Pmin[0].y))
|
|
831
|
+
debug_plot.savefig("Slices", "/tmp/img_{}_{}.png".format(__call_id__, __img_num__))
|
|
832
|
+
__img_num__ += 1
|
|
833
|
+
|
|
834
|
+
try:
|
|
835
|
+
ax = debug_plot.get_ax("Contours")
|
|
836
|
+
ax.plot([x0, V[0]], [y0, V[1]], '-')
|
|
837
|
+
ax.plot(Pmin[0].x, Pmin[0].y, 'o')
|
|
838
|
+
except KeyError:
|
|
839
|
+
pass
|
|
768
840
|
|
|
769
841
|
dist = 0
|
|
770
842
|
|
|
@@ -772,6 +844,7 @@ def slice_contours(data, inner, outer, distance=50, npoints=15, do_fit=False, sh
|
|
|
772
844
|
if show:
|
|
773
845
|
debug_plot.setup_debug("SlicePipe")
|
|
774
846
|
debug_plot.plot("SlicePipe", D, T, '-o')
|
|
847
|
+
debug_plot.savefig("SlicePipe", "/tmp/slice_pipe_{}.png".format(__call_id__))
|
|
775
848
|
|
|
776
849
|
return segments
|
|
777
850
|
|
|
@@ -829,10 +902,12 @@ def find_image_contours(data, params):
|
|
|
829
902
|
print("contour area: {:.3f}".format(area))
|
|
830
903
|
|
|
831
904
|
if params.debug:
|
|
905
|
+
debug_plot.setup_debug("Contours", 1, 1)
|
|
832
906
|
colors = ["#ff9b54", "#ff7f51"] # ["#540b0e", "#9e2a2b"]
|
|
833
907
|
print("Number of countours:", len(out))
|
|
834
908
|
|
|
835
|
-
|
|
909
|
+
ax = debug_plot.get_ax("Contours")
|
|
910
|
+
ax.clear()
|
|
836
911
|
ax.imshow(data, origin='lower', cmap='jet')
|
|
837
912
|
for i, cnt in enumerate(out):
|
|
838
913
|
ax.plot(cnt[:, 0], cnt[:, 1], linewidth=3, color=colors[i % 2])
|
|
@@ -870,6 +945,7 @@ def get_segments(data, params) -> list[Segment]:
|
|
|
870
945
|
list of segments. See `slice_contours`
|
|
871
946
|
|
|
872
947
|
"""
|
|
948
|
+
global the_3d_points
|
|
873
949
|
cntrs = find_image_contours(data, params)
|
|
874
950
|
if cntrs is None:
|
|
875
951
|
return None
|
|
@@ -881,6 +957,7 @@ def get_segments(data, params) -> list[Segment]:
|
|
|
881
957
|
do_fit=params.do_fit,
|
|
882
958
|
show=params.debug)
|
|
883
959
|
|
|
960
|
+
the_3d_points = Segment.get_3d_points_in_list(the_segments)
|
|
884
961
|
return the_segments
|
|
885
962
|
|
|
886
963
|
|
petal_qc/thermal/IRPetalParam.py
CHANGED
|
@@ -12,7 +12,7 @@ class IRPetalParam(object):
|
|
|
12
12
|
values: ArgParser or dict with user values-
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
|
-
self.institute =
|
|
15
|
+
self.institute = None # Either IFIC or DESY to treat the different files
|
|
16
16
|
self.thrs = -22.0 # the threshold
|
|
17
17
|
self.tco2 = -35.0 # Inlet temperature
|
|
18
18
|
self.gauss_size = 15 # Radius of gausian filtering
|
|
@@ -30,7 +30,7 @@ class AnalysisResult(object):
|
|
|
30
30
|
continue
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def show_2D_image(img, title=None):
|
|
33
|
+
def show_2D_image(img, title=None, show_fig=True):
|
|
34
34
|
"""Show a 2D image."""
|
|
35
35
|
if isinstance(img, list):
|
|
36
36
|
fig, ax = plt.subplots(1, len(img))
|
|
@@ -51,8 +51,9 @@ def show_2D_image(img, title=None):
|
|
|
51
51
|
pcm = ax.imshow(img, origin='lower', cmap=HighContrast.reversed()) # cmap="jet")
|
|
52
52
|
fig.colorbar(pcm, ax=ax)
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
if show_fig:
|
|
55
|
+
plt.draw()
|
|
56
|
+
plt.pause(0.001)
|
|
56
57
|
|
|
57
58
|
return fig, ax
|
|
58
59
|
|
petal_qc/thermal/PipeFit.py
CHANGED
|
@@ -413,6 +413,14 @@ class PipeFit(object):
|
|
|
413
413
|
"""
|
|
414
414
|
if M0 is None:
|
|
415
415
|
M = self.initial_guess(data)
|
|
416
|
+
for i, val in enumerate(M):
|
|
417
|
+
if val < self.bounds[0][i]:
|
|
418
|
+
val = 1.01 * self.bounds[0][i]
|
|
419
|
+
M[i] = val
|
|
420
|
+
elif val > self.bounds[1][i]:
|
|
421
|
+
val = 0.99 * self.bounds[0][i]
|
|
422
|
+
M[i] = val
|
|
423
|
+
|
|
416
424
|
if self.debug:
|
|
417
425
|
print("\n** Initial guess")
|
|
418
426
|
self.print_transform(M)
|
|
@@ -498,7 +506,7 @@ class PipeFit(object):
|
|
|
498
506
|
|
|
499
507
|
return X, Y
|
|
500
508
|
|
|
501
|
-
def plot(self):
|
|
509
|
+
def plot(self, show_fig=True):
|
|
502
510
|
"""Plot result of fit and data."""
|
|
503
511
|
fig, ax = plt.subplots(1, 1, tight_layout=True)
|
|
504
512
|
ax.plot(self.pipe[:, 0], self.pipe[:, 1], label="Pipe")
|
|
@@ -509,8 +517,9 @@ class PipeFit(object):
|
|
|
509
517
|
|
|
510
518
|
ax.plot(out[:, 0], out[:, 1], 'o', label="Data")
|
|
511
519
|
ax.legend()
|
|
512
|
-
|
|
513
|
-
|
|
520
|
+
if show_fig:
|
|
521
|
+
plt.draw()
|
|
522
|
+
plt.pause(0.0001)
|
|
514
523
|
return fig, ax
|
|
515
524
|
|
|
516
525
|
|