petal-qc 0.0.17__py3-none-any.whl → 0.0.24__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.
- petal_qc/PetalReceptionTests.py +23 -5
- petal_qc/__init__.py +6 -1
- petal_qc/getPetalCoreTestSummary.py +69 -9
- petal_qc/metrology/PetalMetrology.py +23 -11
- petal_qc/metrology/analyze_locking_points.py +14 -3
- petal_qc/metrology/compare_Cores.py +15 -2
- petal_qc/metrology/convert_mitutoyo.py +5 -0
- petal_qc/metrology/coreMetrology.py +16 -26
- petal_qc/metrology/do_Metrology.py +1 -1
- petal_qc/metrology/petal_flatness.py +10 -9
- petal_qc/metrology/readAVSdata.py +11 -4
- petal_qc/metrology/test_paralelism.py +2 -2
- petal_qc/metrology/uploadPetalInformation.py +35 -3
- petal_qc/readTemplateTable.py +313 -0
- petal_qc/test/analyzeMetrologyTable.py +158 -29
- petal_qc/test/checkPipeShipments.py +60 -0
- petal_qc/test/getAVStests.py +2 -2
- petal_qc/test/reportFromJSon.py +35 -6
- petal_qc/test/testMitutoyo.py +10 -0
- petal_qc/test/thermalReportFromJSon.py +99 -0
- petal_qc/thermal/IRDataGetter.py +2 -0
- petal_qc/thermal/IRPetal.py +20 -6
- petal_qc/thermal/IRPetalParam.py +12 -3
- petal_qc/thermal/Petal_IR_Analysis.py +1 -1
- petal_qc/thermal/PipeFit.py +24 -10
- petal_qc/thermal/PipeIterFit.py +94 -0
- petal_qc/thermal/contours.py +82 -3
- petal_qc/thermal/coreThermal.py +2 -2
- petal_qc/thermal/create_IRCore.py +11 -6
- petal_qc/thermal/create_core_report.py +0 -3
- petal_qc/uploadXrays.py +86 -0
- {petal_qc-0.0.17.dist-info → petal_qc-0.0.24.dist-info}/METADATA +2 -3
- {petal_qc-0.0.17.dist-info → petal_qc-0.0.24.dist-info}/RECORD +36 -30
- {petal_qc-0.0.17.dist-info → petal_qc-0.0.24.dist-info}/WHEEL +1 -1
- {petal_qc-0.0.17.dist-info → petal_qc-0.0.24.dist-info}/entry_points.txt +1 -0
- {petal_qc-0.0.17.dist-info → petal_qc-0.0.24.dist-info}/top_level.txt +0 -0
|
@@ -317,7 +317,10 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
317
317
|
return
|
|
318
318
|
|
|
319
319
|
self.find_petal(SN, silent=True)
|
|
320
|
-
if self.petal_core:
|
|
320
|
+
if self.petal_core and self.petal_core["alternativeIdentifier"] is not None:
|
|
321
|
+
if len(self.petal_core["batches"])==0:
|
|
322
|
+
ITkDButils.set_petal_core_batch(self.session, self.petal_core)
|
|
323
|
+
|
|
321
324
|
return
|
|
322
325
|
|
|
323
326
|
dialog = Gtk.MessageDialog(
|
|
@@ -340,7 +343,7 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
340
343
|
if len(petal_alias) == 0:
|
|
341
344
|
petal_alias = self.alias
|
|
342
345
|
|
|
343
|
-
rc = ITkDButils.registerPetalCore(self.session, SN, petal_alias)
|
|
346
|
+
rc = ITkDButils.registerPetalCore(self.session, SN, petal_alias, petal_core=self.petal_core)
|
|
344
347
|
if rc is None:
|
|
345
348
|
dbGtkUtils.complain("Could not Register petal {} ({})".format(SN, petal_alias))
|
|
346
349
|
|
|
@@ -642,6 +645,7 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
642
645
|
|
|
643
646
|
values = dctD.values
|
|
644
647
|
values["component"] = SN
|
|
648
|
+
self.check_retroactive_upload(values)
|
|
645
649
|
print(json.dumps(values, indent=2))
|
|
646
650
|
rc = ITkDButils.upload_test(self.session, values)
|
|
647
651
|
if rc is not None:
|
|
@@ -681,7 +685,7 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
681
685
|
self.check_tests(True)
|
|
682
686
|
|
|
683
687
|
def check_tests(self, do_write=False):
|
|
684
|
-
"""Check whether all tests are
|
|
688
|
+
"""Check whether all tests are fine"""
|
|
685
689
|
nbad = 0
|
|
686
690
|
bad = []
|
|
687
691
|
for test in self.test_list:
|
|
@@ -712,6 +716,17 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
712
716
|
"""Assembly button clicked."""
|
|
713
717
|
self.check_assembly(self.DESY_comp)
|
|
714
718
|
|
|
719
|
+
def check_retroactive_upload(self, values):
|
|
720
|
+
"""Check whether retroactive upload is needed."""
|
|
721
|
+
if self.petal_core is None:
|
|
722
|
+
self.query_db()
|
|
723
|
+
if self.petal_core is None:
|
|
724
|
+
return
|
|
725
|
+
|
|
726
|
+
location = self.petal_core["currentLocation"]["code"]
|
|
727
|
+
if location != values["institution"]:
|
|
728
|
+
values["isRetroactive"] = True
|
|
729
|
+
|
|
715
730
|
def on_upload(self, widget):
|
|
716
731
|
"""Upload tests to DB."""
|
|
717
732
|
if self.petal_core is None:
|
|
@@ -719,8 +734,25 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
|
|
|
719
734
|
if self.petal_core is None:
|
|
720
735
|
return
|
|
721
736
|
|
|
737
|
+
# First Visual Inspection
|
|
722
738
|
for test in self.test_list:
|
|
723
739
|
values = test.values
|
|
740
|
+
if values["testType"] != "VISUAL_INSPECTION":
|
|
741
|
+
continue
|
|
742
|
+
|
|
743
|
+
self.check_retroactive_upload(values)
|
|
744
|
+
self.write_message("{}\n".format(values["testType"]))
|
|
745
|
+
res = ITkDButils.upload_test(self.session, values, check_runNumber=True)
|
|
746
|
+
if res is not None:
|
|
747
|
+
dbGtkUtils.complain("Could not upload test {}".format(values["testType"]), res)
|
|
748
|
+
|
|
749
|
+
# Then the rest
|
|
750
|
+
for test in self.test_list:
|
|
751
|
+
values = test.values
|
|
752
|
+
if values["testType"] == "VISUAL_INSPECTION":
|
|
753
|
+
continue
|
|
754
|
+
|
|
755
|
+
self.check_retroactive_upload(values)
|
|
724
756
|
self.write_message("{}\n".format(values["testType"]))
|
|
725
757
|
res = ITkDButils.upload_test(self.session, values, check_runNumber=True)
|
|
726
758
|
if res is not None:
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Read Python table with reception tests."""
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import math
|
|
6
|
+
import argparse
|
|
7
|
+
import pandas as pd
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from itkdb_gtk import ITkDBlogin, ITkDButils
|
|
12
|
+
|
|
13
|
+
def check_value(value):
|
|
14
|
+
"""Check that value is valid."""
|
|
15
|
+
if value is None:
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
if isinstance(value, float):
|
|
19
|
+
if math.isnan(value):
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def string_to_boolean(s):
|
|
26
|
+
"""Converts a string to a boolean."""
|
|
27
|
+
val = s.lower()
|
|
28
|
+
if val=="pass" or val=="true" or val=="1":
|
|
29
|
+
return True
|
|
30
|
+
elif val=="fail" or val=="false" or val=="0":
|
|
31
|
+
return False
|
|
32
|
+
else:
|
|
33
|
+
raise ValueError
|
|
34
|
+
|
|
35
|
+
def parse_value(value):
|
|
36
|
+
"""Parse value in cell."""
|
|
37
|
+
try:
|
|
38
|
+
spassed, comment = value.split(",")
|
|
39
|
+
except ValueError:
|
|
40
|
+
spassed = value
|
|
41
|
+
comment = ""
|
|
42
|
+
|
|
43
|
+
passed = string_to_boolean(spassed)
|
|
44
|
+
if passed is None:
|
|
45
|
+
return None, None
|
|
46
|
+
|
|
47
|
+
return passed, comment
|
|
48
|
+
|
|
49
|
+
def create_dto(session, SN, test_name):
|
|
50
|
+
"""REturns the test DTO."""
|
|
51
|
+
user = ITkDButils.get_db_user(session)
|
|
52
|
+
defaults = {
|
|
53
|
+
"component": SN,
|
|
54
|
+
"institution": user["institutions"][0]["code"],
|
|
55
|
+
"runNumber": "1",
|
|
56
|
+
}
|
|
57
|
+
dto = ITkDButils.get_test_skeleton(session, "CORE_PETAL", test_name, defaults)
|
|
58
|
+
return dto
|
|
59
|
+
|
|
60
|
+
def do_visual_inspection(session, core, value):
|
|
61
|
+
"""Uploads visual inspection."""
|
|
62
|
+
if not check_value(value):
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
SN = core["serialNumber"]
|
|
66
|
+
dto = create_dto(session, SN, "VISUAL_INSPECTION")
|
|
67
|
+
|
|
68
|
+
passed, comment = parse_value(value)
|
|
69
|
+
|
|
70
|
+
if passed is None:
|
|
71
|
+
print("Wrong value fpr PASS/FAIL {} in {} for {}".format(value, "VISUAL_INSPECTION", core["alternativeIdentifier"]) )
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
if passed:
|
|
75
|
+
dto["passed"] = True
|
|
76
|
+
else:
|
|
77
|
+
dto["passed"] = False
|
|
78
|
+
dto["defects"].append({
|
|
79
|
+
"name": "VISUAL",
|
|
80
|
+
"description": comment,
|
|
81
|
+
"properties": {}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
return dto
|
|
85
|
+
|
|
86
|
+
def do_grounding(session, core, value):
|
|
87
|
+
"""Uploads grounding check"""
|
|
88
|
+
if not check_value(value):
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
SN = core["serialNumber"]
|
|
92
|
+
dto = create_dto(session, SN, "GROUNDING_CHECK")
|
|
93
|
+
|
|
94
|
+
fb, pipes, pipe_gnd = [float(x) for x in value.split(',')]
|
|
95
|
+
if fb > 2.0:
|
|
96
|
+
dto["passed"] = False
|
|
97
|
+
dto["defects"].append({
|
|
98
|
+
"name": "GROUND_FB",
|
|
99
|
+
"description": "resistance front-back is {} > 2 Ohm".format(fb),
|
|
100
|
+
"properties": {}
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
if pipes>0 and pipes<20.0e6:
|
|
104
|
+
dto["passed"] = False
|
|
105
|
+
dto["defects"].append({
|
|
106
|
+
"name": "GROUND_PIPES",
|
|
107
|
+
"description": "resistance between pipes is {} < 20 MOhm".format(pipes),
|
|
108
|
+
"properties": {}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
if pipe_gnd>0 and pipe_gnd<20.0e6:
|
|
112
|
+
dto["passed"] = False
|
|
113
|
+
dto["defects"].append({
|
|
114
|
+
"name": "GROUND_PIPE_GND",
|
|
115
|
+
"description": "resistance between pipes and GNDis {} < 20 MOhm".format(pipe_gnd),
|
|
116
|
+
"properties": {}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
dto["results"]["RESISTANCE_FB"] = fb
|
|
120
|
+
dto["results"]["RESISTANCE_PIPES"] = pipes
|
|
121
|
+
dto["results"]["RESISTANCE_PIPE_GND"] = pipe_gnd
|
|
122
|
+
|
|
123
|
+
return dto
|
|
124
|
+
|
|
125
|
+
def do_bending(session, core, value):
|
|
126
|
+
"""Uploads bending."""
|
|
127
|
+
if not check_value(value):
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
SN = core["serialNumber"]
|
|
131
|
+
dto = create_dto(session, SN, "BENDING120")
|
|
132
|
+
passed, comment = parse_value(value)
|
|
133
|
+
if passed is None:
|
|
134
|
+
print("Wrong value fpr PASS/FAIL {} in {} for {}".format(value, "BENDING120", core["alternativeIdentifier"]) )
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
if passed:
|
|
138
|
+
dto["passed"] = True
|
|
139
|
+
else:
|
|
140
|
+
dto["passed"] = False
|
|
141
|
+
dto["defects"].append({
|
|
142
|
+
"name": "BENDING120",
|
|
143
|
+
"description": comment,
|
|
144
|
+
"properties": {}
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
return dto
|
|
148
|
+
|
|
149
|
+
def do_weight(session, core, value):
|
|
150
|
+
"""Uploads weight."""
|
|
151
|
+
if not check_value(value):
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
SN = core["serialNumber"]
|
|
155
|
+
dto = create_dto(session, SN, "PETAL_CORE_WEIGHT")
|
|
156
|
+
|
|
157
|
+
weight = float(value)
|
|
158
|
+
dto["results"]["WEIGHT"] = weight
|
|
159
|
+
if abs(weight-250)>25:
|
|
160
|
+
dto["passed"] = False
|
|
161
|
+
dto["defects"].append({
|
|
162
|
+
"name": "WEIGHT",
|
|
163
|
+
"description": "Petal core wights {:.1f} more than 25 gr. beyond 250.".format(weight),
|
|
164
|
+
"properties": {}
|
|
165
|
+
})
|
|
166
|
+
else:
|
|
167
|
+
dto["passed"] = True
|
|
168
|
+
|
|
169
|
+
return dto
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def do_thickness(session, core, value):
|
|
173
|
+
"""Uploads thickness."""
|
|
174
|
+
if not check_value(value):
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
SN = core["serialNumber"]
|
|
178
|
+
dto = create_dto(session, SN, "CORE_THICKNESS")
|
|
179
|
+
thickness = float(value)
|
|
180
|
+
dto["results"]["THICKNESS"] = thickness
|
|
181
|
+
|
|
182
|
+
dto["passed"] = True
|
|
183
|
+
if abs(thickness-5.9)>0.25:
|
|
184
|
+
dto["problems"] = True
|
|
185
|
+
dto["comments"].append("Petal core wights {:.1f} more than 25 gr. beyond 250.".format(thickness))
|
|
186
|
+
|
|
187
|
+
return dto
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def do_metrology_template(session, core, value):
|
|
191
|
+
"""Uploads metrology template."""
|
|
192
|
+
if not check_value(value):
|
|
193
|
+
return None
|
|
194
|
+
|
|
195
|
+
SN = core["serialNumber"]
|
|
196
|
+
dto = create_dto(session, SN, "METROLOGY_TEMPLATE")
|
|
197
|
+
passed, comment = parse_value(value)
|
|
198
|
+
if passed is None:
|
|
199
|
+
print("Wrong value fpr PASS/FAIL {} in {} for {}".format(value, "TEMPLATE", core["alternativeIdentifier"]) )
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
if passed:
|
|
203
|
+
dto["passed"] = True
|
|
204
|
+
else:
|
|
205
|
+
dto["passed"] = False
|
|
206
|
+
dto["defects"].append({
|
|
207
|
+
"name": "TEMPLATE",
|
|
208
|
+
"description": comment,
|
|
209
|
+
"properties": {}
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
return dto
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def do_delamination(session, core, value):
|
|
216
|
+
"""Uploads delamination."""
|
|
217
|
+
if not check_value(value):
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
SN = core["serialNumber"]
|
|
221
|
+
dto = create_dto(session, SN, "DELAMINATION")
|
|
222
|
+
|
|
223
|
+
passed, comment = parse_value(value)
|
|
224
|
+
if passed is None:
|
|
225
|
+
print("Wrong value fpr PASS/FAIL {} in {} for {}".format(value, "DELAMINATION", core["alternativeIdentifier"]) )
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
if passed:
|
|
229
|
+
dto["passed"] = True
|
|
230
|
+
else:
|
|
231
|
+
dto["passed"] = False
|
|
232
|
+
dto["defects"].append({
|
|
233
|
+
"name": "DELAMINATION",
|
|
234
|
+
"description": comment,
|
|
235
|
+
"properties": {}
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
return dto
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def readTemplateTable(session, options):
|
|
242
|
+
"""Main entry.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
session (itkdb.Session): The PDB client.
|
|
246
|
+
options: program options
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
core_tests = {
|
|
250
|
+
"VISUAL_INSPECTION": do_visual_inspection,
|
|
251
|
+
"GROUNDING_CHECK": do_grounding,
|
|
252
|
+
"BENDING120": do_bending,
|
|
253
|
+
"PETAL_CORE_WEIGHT": do_weight,
|
|
254
|
+
"CORE_THICKNESS": do_thickness,
|
|
255
|
+
"METROLOGY_TEMPLATE": do_metrology_template,
|
|
256
|
+
"DELAMINATION": do_delamination
|
|
257
|
+
}
|
|
258
|
+
try:
|
|
259
|
+
sheet = int(options.sheet)
|
|
260
|
+
except ValueError:
|
|
261
|
+
sheet = options.sheet
|
|
262
|
+
|
|
263
|
+
df = pd.read_excel(options.files[0], sheet_name=sheet)
|
|
264
|
+
#print(df)
|
|
265
|
+
|
|
266
|
+
for row in df.itertuples():
|
|
267
|
+
petal_id = row.CORE_ID
|
|
268
|
+
if not check_value(petal_id):
|
|
269
|
+
break
|
|
270
|
+
|
|
271
|
+
print("\n\n### {}".format(petal_id))
|
|
272
|
+
core = ITkDButils.get_DB_component(session, petal_id)
|
|
273
|
+
for test, func in core_tests.items():
|
|
274
|
+
data = func(session, core, getattr(row, test))
|
|
275
|
+
if data is None:
|
|
276
|
+
continue
|
|
277
|
+
|
|
278
|
+
data["properties"]["OPERATOR"] = options.operator
|
|
279
|
+
|
|
280
|
+
#print(json.dumps(data, indent=3))
|
|
281
|
+
rc = ITkDButils.upload_test(session, data, check_runNumber=True)
|
|
282
|
+
if rc:
|
|
283
|
+
print("\n*** Could not upload test {} for {}".format(test, petal_id))
|
|
284
|
+
print(rc)
|
|
285
|
+
print()
|
|
286
|
+
|
|
287
|
+
def main():
|
|
288
|
+
"""Entry point."""
|
|
289
|
+
parser = argparse.ArgumentParser()
|
|
290
|
+
parser.add_argument("files", nargs='*', help="The template spreadsheet")
|
|
291
|
+
parser.add_argument("--sheet", default="0", help="Sheet to read from excel file.")
|
|
292
|
+
parser.add_argument("--operator", default="Oihan Elesgaray", help="Name of operator.")
|
|
293
|
+
|
|
294
|
+
args = parser.parse_args()
|
|
295
|
+
if len(args.files) == 0:
|
|
296
|
+
print("I need an input file")
|
|
297
|
+
sys.exit()
|
|
298
|
+
|
|
299
|
+
if not Path(args.files[0]).exists():
|
|
300
|
+
print("Input file does not exist.")
|
|
301
|
+
sys.exit()
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# ITk_PB authentication
|
|
305
|
+
dlg = ITkDBlogin.ITkDBlogin()
|
|
306
|
+
pdb_session = dlg.get_client()
|
|
307
|
+
|
|
308
|
+
readTemplateTable(pdb_session, args)
|
|
309
|
+
|
|
310
|
+
dlg.die()
|
|
311
|
+
|
|
312
|
+
if __name__ == "__main__":
|
|
313
|
+
main()
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Analyze the table generated by createMetrologyTable.
|
|
2
|
+
"""Analyze the table generated by createMetrologyTable.
|
|
3
|
+
|
|
4
|
+
It should also work with the table created by analyzeMetrologyTable, which is
|
|
5
|
+
the new default.
|
|
6
|
+
"""
|
|
3
7
|
|
|
4
8
|
import sys
|
|
5
9
|
from pathlib import Path
|
|
@@ -13,7 +17,22 @@ from lmfit.models import LinearModel
|
|
|
13
17
|
|
|
14
18
|
from petal_qc.utils.fit_utils import draw_best_fit
|
|
15
19
|
|
|
20
|
+
fig_width = 12.0
|
|
21
|
+
fig_height = 1.2*fig_width/3.0
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
16
25
|
def distance(P1, P2, P3):
|
|
26
|
+
"""Distance of P3 to line defined by P1-P2.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
P1: Point 1 of the line
|
|
30
|
+
P2: Point 2 of the line
|
|
31
|
+
P3: Actual point
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
float: distance
|
|
35
|
+
"""
|
|
17
36
|
C = np.cross(P2-P1, P3-P1)
|
|
18
37
|
D = C/norm(P2-P1)
|
|
19
38
|
return D
|
|
@@ -38,14 +57,41 @@ def remove_outliers_indx(data, cut=2.0, debug=False):
|
|
|
38
57
|
indx = np.where(s < cut)[0]
|
|
39
58
|
return indx
|
|
40
59
|
|
|
60
|
+
def draw_delta_scatter(ax, x, y, title, x_lim=None, y_lim=None, radius=None):
|
|
41
61
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
fig_width = 12.0
|
|
45
|
-
fig_height = 1.2*fig_width/3.0
|
|
62
|
+
if x_lim is None:
|
|
63
|
+
x_lim=(-150, 150)
|
|
46
64
|
|
|
47
|
-
|
|
65
|
+
if y_lim is None:
|
|
66
|
+
y_lim=(-150, 150)
|
|
67
|
+
|
|
68
|
+
if radius is None:
|
|
69
|
+
radius = (25, 100)
|
|
70
|
+
|
|
71
|
+
ax.set_title(title)
|
|
72
|
+
ax.set_aspect('equal', adjustable='box')
|
|
73
|
+
ax.set_xlim(x_lim)
|
|
74
|
+
ax.set_ylim(y_lim)
|
|
75
|
+
circle = plt.Circle((0,0), radius[1], color="red", alpha=0.25)
|
|
76
|
+
ax.add_patch(circle)
|
|
77
|
+
circle = plt.Circle((0,0), radius[0], color="green", alpha=0.25)
|
|
78
|
+
ax.add_patch(circle)
|
|
48
79
|
|
|
80
|
+
ax.set_xlabel("X (µm)")
|
|
81
|
+
ax.set_ylabel("Y (µm)")
|
|
82
|
+
ax.grid()
|
|
83
|
+
|
|
84
|
+
ax.scatter(x, y, marker='.')
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def analyze_fiducials(options, T):
|
|
88
|
+
"""Analyze relative position of locator fiducials.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
options (_type_): Program options
|
|
92
|
+
T (DataFrame): Pandas data frame.
|
|
93
|
+
"""
|
|
94
|
+
side = T["side"].values[0]
|
|
49
95
|
if options.mould > 0:
|
|
50
96
|
x = 1000*T.loc[T['mould'] == options.mould, 'fd_dx'].values
|
|
51
97
|
y = 1000*T.loc[T['mould'] == options.mould, 'fd_dy'].values
|
|
@@ -54,22 +100,23 @@ def main(options):
|
|
|
54
100
|
x = 1000*T['fd_dx'].values
|
|
55
101
|
y = 1000*T['fd_dy'].values
|
|
56
102
|
|
|
57
|
-
fig, ax = plt.subplots(nrows=1, ncols=
|
|
58
|
-
fig.suptitle("Relative Position FD01-FD02")
|
|
59
|
-
ax[0]
|
|
60
|
-
ax[0].
|
|
61
|
-
ax[0].
|
|
62
|
-
ax[0].
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
ax[0].
|
|
70
|
-
ax[0].
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
fig, ax = plt.subplots(nrows=1, ncols=2, tight_layout=True, figsize=(fig_width, fig_height))
|
|
104
|
+
fig.suptitle("Relative Position FD01-FD02 [{}]".format(side))
|
|
105
|
+
draw_delta_scatter(ax[0], x, y, "FD01-FD02")
|
|
106
|
+
# ax[0].set_title("FD01-FD02")
|
|
107
|
+
# ax[0].set_aspect('equal', adjustable='box')
|
|
108
|
+
# ax[0].set_xlim(-150, 150)
|
|
109
|
+
# ax[0].set_ylim(-150, 150)
|
|
110
|
+
# circle = plt.Circle((0,0), 100, color="red", alpha=0.25)
|
|
111
|
+
# ax[0].add_patch(circle)
|
|
112
|
+
# circle = plt.Circle((0,0), 25, color="green", alpha=0.25)
|
|
113
|
+
# ax[0].add_patch(circle)
|
|
114
|
+
#
|
|
115
|
+
# ax[0].set_xlabel("X (µm)")
|
|
116
|
+
# ax[0].set_ylabel("Y (µm)")
|
|
117
|
+
# ax[0].grid()
|
|
118
|
+
#
|
|
119
|
+
# ax[0].scatter(x, y, marker='.')
|
|
73
120
|
|
|
74
121
|
model = LinearModel()
|
|
75
122
|
params = model.guess(y, x=x)
|
|
@@ -94,15 +141,94 @@ def main(options):
|
|
|
94
141
|
angle = 180*math.atan( result.best_values['slope'])/math.pi
|
|
95
142
|
print("angle {:.5f} deg.".format(angle))
|
|
96
143
|
|
|
97
|
-
ax[1].set_xlim(-
|
|
98
|
-
ax[1].set_xlabel("
|
|
144
|
+
ax[1].set_xlim(-50, 50)
|
|
145
|
+
ax[1].set_xlabel("distance to line (µm)")
|
|
99
146
|
ax[1].grid()
|
|
100
|
-
ax[1].hist(
|
|
147
|
+
ax[1].hist(values)
|
|
148
|
+
|
|
149
|
+
# ax[2].set_xlim(-75, 75)
|
|
150
|
+
# ax[2].set_xlabel("delta_X (µm)")
|
|
151
|
+
# ax[2].grid()
|
|
152
|
+
# ax[2].hist(x)
|
|
153
|
+
|
|
154
|
+
# ax[3].set_xlim(-150, 150)
|
|
155
|
+
# ax[3].set_xlabel("delta_Y (µm)")
|
|
156
|
+
# ax[3].grid()
|
|
157
|
+
# ax[3].hist(y)
|
|
158
|
+
|
|
159
|
+
def analyze_delta_pos(options, T):
|
|
160
|
+
""" Study dependency of delta pos in PL01-FD01 with the other locators.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
options (_type_): Program options
|
|
164
|
+
T (DataFrame): Pandas data frame.
|
|
165
|
+
"""
|
|
166
|
+
side = T["side"].values[0]
|
|
167
|
+
x = T["pl01_dx"].values
|
|
168
|
+
y = T["pl01_dy"].values
|
|
169
|
+
delta_pl01 = 1000*np.column_stack((x, y))
|
|
170
|
+
norm = np.array([ np.linalg.norm(P) for P in delta_pl01])
|
|
171
|
+
indx = np.where(norm<75.0)
|
|
172
|
+
|
|
173
|
+
delta_pl02 = 1000*np.column_stack((T["pl02_dx"].values, T["pl02_dy"].values))
|
|
174
|
+
delta_pl03 = 1000*np.column_stack((T["pl03_dx"].values, T["pl03_dy"].values))
|
|
175
|
+
|
|
176
|
+
fig, ax = plt.subplots(nrows=1, ncols=2, tight_layout=True, figsize=(fig_width, fig_height))
|
|
177
|
+
fig.suptitle("Delta from PL01 [{}]".format(side))
|
|
178
|
+
draw_delta_scatter(ax[0], delta_pl02[indx, 0], delta_pl02[indx, 1], "PL02")
|
|
179
|
+
draw_delta_scatter(ax[1], delta_pl03[indx, 0], delta_pl03[indx, 1], "PL02")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def analyze_parallelism(options, T):
|
|
183
|
+
"""Analyze parallelism.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
options (_type_): Program options
|
|
187
|
+
T (DataFrame): Pandas data frame.
|
|
188
|
+
"""
|
|
189
|
+
if options.institute is None:
|
|
190
|
+
df = T
|
|
191
|
+
else:
|
|
192
|
+
df = T.loc[T["institute"] == options.institute]
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
side = df["side"].values[0]
|
|
196
|
+
labels = []
|
|
197
|
+
for L in df["petal_id"].values:
|
|
198
|
+
ival = int(L[5:])
|
|
199
|
+
labels.append(ival)
|
|
200
|
+
|
|
201
|
+
x = 1000*df["flatness"].values
|
|
202
|
+
y = 1000*df["parallelism"].values
|
|
203
|
+
|
|
204
|
+
fig, ax = plt.subplots(nrows=1, ncols=1, tight_layout=True)
|
|
205
|
+
fig.suptitle("Parallelism .vs. flatness [{}]".format(side))
|
|
206
|
+
|
|
207
|
+
ax.scatter(x, y, marker='.')
|
|
208
|
+
for xp, yp, lbl in zip(x, y, labels):
|
|
209
|
+
ax.text(xp, yp, "{}".format(lbl))
|
|
210
|
+
|
|
211
|
+
ax.set_xlabel("flatness (µm)")
|
|
212
|
+
ax.set_ylabel("parallelism (µm)")
|
|
213
|
+
ax.grid()
|
|
214
|
+
|
|
215
|
+
fig, ax = plt.subplots(nrows=1, ncols=1, tight_layout=True)
|
|
216
|
+
fig.suptitle("Offset [{}]".format(side))
|
|
217
|
+
ax.hist(1000*T["offset"].values)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def main(options):
|
|
221
|
+
"""main entry."""
|
|
222
|
+
T = pd.read_csv(options.files[0])
|
|
223
|
+
|
|
224
|
+
# analyze fiducials
|
|
225
|
+
analyze_fiducials(options, T)
|
|
226
|
+
|
|
227
|
+
# Understand deviation from nominal.
|
|
228
|
+
analyze_delta_pos(options, T)
|
|
101
229
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
ax[2].grid()
|
|
105
|
-
ax[2].hist(y)
|
|
230
|
+
# Correlate planarity y parallelism
|
|
231
|
+
analyze_parallelism(options, T)
|
|
106
232
|
|
|
107
233
|
plt.show()
|
|
108
234
|
|
|
@@ -110,6 +236,9 @@ if __name__ == "__main__":
|
|
|
110
236
|
parser = argparse.ArgumentParser()
|
|
111
237
|
parser.add_argument('files', nargs='*', help="Input files")
|
|
112
238
|
parser.add_argument('--mould', default=-1, type=int, help="mould index")
|
|
239
|
+
parser.add_argument("--institute",
|
|
240
|
+
default=None,
|
|
241
|
+
help="Either IFIC or DESY to treat the different files")
|
|
113
242
|
|
|
114
243
|
opts = parser.parse_args()
|
|
115
244
|
if len(opts.files) == 0:
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""List pipe shipments."""
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from itkdb_gtk import ITkDBlogin, ITkDButils
|
|
7
|
+
|
|
8
|
+
def main(session):
|
|
9
|
+
"""List shipments from DESY to AVS containing PIPES."""
|
|
10
|
+
payload = {
|
|
11
|
+
"filterMap": {
|
|
12
|
+
"sender": "DESYHH",
|
|
13
|
+
"recipient": ["AVS"],
|
|
14
|
+
"status": "delivered"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Loop over shipments
|
|
19
|
+
shpmts = session.get("listShipmentsByInstitution", json=payload)
|
|
20
|
+
for s in shpmts:
|
|
21
|
+
items = session.get("listShipmentItems", json={"shipment": s["id"]})
|
|
22
|
+
pipes = []
|
|
23
|
+
for it in items:
|
|
24
|
+
if it["component"]["componentType"]['code'] == "COOLING_LOOP_PETAL":
|
|
25
|
+
pipes.append(it)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if len(pipes) == 0:
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
print("Shipment {}".format(s["name"]))
|
|
32
|
+
print(":> {}".format(s["sentTs"]))
|
|
33
|
+
for c in pipes:
|
|
34
|
+
pid = c["component"]["alternativeIdentifier"]
|
|
35
|
+
print("*-- {}".format(pid))
|
|
36
|
+
|
|
37
|
+
the_pipe = ITkDButils.get_DB_component(session, c["component"]["serialNumber"])
|
|
38
|
+
if the_pipe is None:
|
|
39
|
+
print(" !! ERROR: Could not retrieve component {} !!".format(c["component"]["serialNumber"]))
|
|
40
|
+
continue
|
|
41
|
+
|
|
42
|
+
if the_pipe["parents"] is not None:
|
|
43
|
+
for p in the_pipe["parents"]:
|
|
44
|
+
if p["componentType"]["code"] == "CORE_PETAL":
|
|
45
|
+
print( " -> Core Petal: {} [{}]".format(p["component"]["alternativeIdentifier"],the_pipe["currentLocation"]["code"]) )
|
|
46
|
+
|
|
47
|
+
print("\n")
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
# ITk_PB authentication
|
|
51
|
+
dlg = ITkDBlogin.ITkDBlogin()
|
|
52
|
+
client = dlg.get_client()
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
main(client)
|
|
56
|
+
|
|
57
|
+
except Exception as E:
|
|
58
|
+
print(E)
|
|
59
|
+
|
|
60
|
+
dlg.die()
|
petal_qc/test/getAVStests.py
CHANGED
|
@@ -323,10 +323,10 @@ if __name__ == "__main__":
|
|
|
323
323
|
parser.add_argument("--cores", dest="cores", action=RangeListAction, default=[],
|
|
324
324
|
help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
|
|
325
325
|
|
|
326
|
-
|
|
326
|
+
opts = parser.parse_args()
|
|
327
327
|
dlg = ITkDBlogin.ITkDBlogin()
|
|
328
328
|
session = dlg.get_client()
|
|
329
329
|
|
|
330
|
-
main(session,
|
|
330
|
+
main(session, opts)
|
|
331
331
|
|
|
332
332
|
dlg.die()
|