petal-qc 0.0.16__py3-none-any.whl → 0.0.18__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.

@@ -14,9 +14,12 @@ The main routine is BTreport and can be called from anywhere else.
14
14
  import sys
15
15
  import traceback
16
16
  import json
17
- import getpass
18
17
  import datetime
19
18
  import dateutil.parser
19
+ import argparse
20
+
21
+ from petal_qc.utils.ArgParserUtils import RangeListAction
22
+
20
23
  import itkdb
21
24
  from itkdb_gtk import ITkDBlogin
22
25
  from itkdb_gtk import ITkDButils
@@ -88,7 +91,7 @@ def find_bus_tapes(session, petal, complain_func=complain):
88
91
  if cstage != "COMPLETED":
89
92
  complain_func("Bus tape not in final stages", cstage)
90
93
  bt_valid[comp_type] = False
91
-
94
+
92
95
  else:
93
96
  bt_valid[comp_type] = True
94
97
 
@@ -108,8 +111,8 @@ def find_but_tape_tests(session, petal_date, bt_sn, complain_func=complain):
108
111
  dict: dict with all tests. key is the test type code.
109
112
 
110
113
  """
111
- test_list = session.get("listTestRunsByComponent",
112
- json={"filterMap":{"serialNumber": bt_sn,
114
+ test_list = session.get("listTestRunsByComponent",
115
+ json={"filterMap":{"serialNumber": bt_sn,
113
116
  "stage": "COMPLETED"}
114
117
  })
115
118
  bt_tests = {}
@@ -147,7 +150,7 @@ def date2string(the_date=None):
147
150
  return out
148
151
 
149
152
 
150
- def BTreport(session, SerialN, complain_func=complain):
153
+ def BTreport(session, SerialN, petal=None, complain_func=complain):
151
154
  """Makes the BTreport for a petal core.
152
155
 
153
156
  Args:
@@ -155,20 +158,21 @@ def BTreport(session, SerialN, complain_func=complain):
155
158
  SerialN (str): The Petal core SB
156
159
  """
157
160
  # get petal frm DB.
158
- petal = ITkDButils.get_DB_component(session, SerialN)
159
161
  if petal is None:
160
- complain_func(SerialN, "Could not find petal core.")
161
- return None
162
+ petal = ITkDButils.get_DB_component(session, SerialN)
163
+ if petal is None:
164
+ complain_func(SerialN, "Could not find petal core.")
165
+ return None
162
166
 
163
167
  SerialN = petal["serialNumber"]
164
168
 
165
- print("+++ Petal core {} [{}]".format(SerialN, petal["alternativeIdentifier"]))
169
+ print("\n+++ Petal core {} [{}]".format(SerialN, petal["alternativeIdentifier"]))
166
170
  petal_date = dateutil.parser.parse(petal["stateTs"])
167
171
  comp_type = get_type(petal)
168
172
  if comp_type != "CORE_AVS":
169
173
  complain_func("This is not a petal cores", comp_type)
170
174
  return None
171
-
175
+
172
176
  # Check that the petal core is in the proper stage.
173
177
  stage = petal["currentStage"]['code']
174
178
  if stage != "AT_QC_SITE":
@@ -182,12 +186,12 @@ def BTreport(session, SerialN, complain_func=complain):
182
186
 
183
187
  # Loop on children an find bustapes
184
188
  bt_list, bt_valid = find_bus_tapes(session, petal, complain_func=complain_func)
185
-
189
+
186
190
  nvalid = 0
187
191
  for valid in bt_valid.values():
188
192
  if valid:
189
193
  nvalid += 1
190
-
194
+
191
195
  if nvalid != 2:
192
196
  complain_func("no valid bustape found", "Either not assembled or in incorrect stage.")
193
197
  return None
@@ -210,6 +214,7 @@ def BTreport(session, SerialN, complain_func=complain):
210
214
  # Check the tests in the bustapes
211
215
  ngood = 0
212
216
  ntrouble = 0
217
+ nprocess = 0
213
218
  for bt, cp_id in bt_list.values():
214
219
  bt_sn = bt["serialNumber"]
215
220
  print("bus tape {}".format(bt_sn))
@@ -218,7 +223,11 @@ def BTreport(session, SerialN, complain_func=complain):
218
223
  bt_nprob = 0
219
224
  # get list of tests and select the latest.
220
225
  bt_tests = find_but_tape_tests(session, petal_date, bt_sn, complain_func=complain_func)
221
-
226
+ if len(bt_tests) == 0:
227
+ print("-> No bus tape tests available")
228
+ continue
229
+
230
+ nprocess += 1
222
231
  results = {}
223
232
  childId = {}
224
233
  for key, the_test in bt_tests.items():
@@ -248,19 +257,62 @@ def BTreport(session, SerialN, complain_func=complain):
248
257
  # {"value": childId["BTSTRETCHP"],
249
258
  # "childParentRelation": cp_id})
250
259
 
260
+ if nprocess == 0:
261
+ return None
262
+
251
263
  out["passed"] = (ngood == 4)
252
264
  out["problems"] = (ntrouble > 0)
253
265
  print("BusTape Report\n\tN. good {}\n\tN. prob {}".format(ngood, ntrouble))
254
266
 
255
267
  return out
256
268
 
269
+
270
+ def check_petal_core(session, SerialN):
271
+ """Check petal core for bt report."""
272
+ core = ITkDButils.get_DB_component(session, SerialN)
273
+ if core is None:
274
+ return None
275
+
276
+ test_list = session.get(
277
+ "listTestRunsByComponent",
278
+ json={
279
+ "filterMap": {
280
+ "serialNumber": core["serialNumber"],
281
+ "state": "ready",
282
+ "testType": ["BTTESTING",],
283
+ }
284
+ },
285
+ )
286
+
287
+ ntest = 0
288
+ for tst in test_list:
289
+ ntest += 1
290
+
291
+ if ntest>0:
292
+ return None
293
+
294
+ return core
295
+
257
296
  def main():
258
297
  """Main entry."""
259
- try:
260
- SN = sys.argv[1]
261
- except IndexError:
262
- print("I need a petal core SN or AlternativeID")
263
- sys.exit()
298
+ parser = argparse.ArgumentParser()
299
+ parser.add_argument("args", nargs='*', help="Input cores")
300
+ parser.add_argument("--cores", dest="cores", action=RangeListAction, default=[],
301
+ help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
302
+
303
+
304
+ args = parser.parse_args()
305
+ if len(args.cores)==0:
306
+ try:
307
+ args.cores.extend(args.args)
308
+
309
+ except IndexError:
310
+ print("I need a petal core SN or AlternativeID")
311
+ sys.exit()
312
+
313
+ else:
314
+ cores = [ "PPC.{:03d}".format(int(x)) for x in args.cores]
315
+ args.cores = cores
264
316
 
265
317
  # ITk PDB authentication
266
318
  dlg = None
@@ -272,27 +324,34 @@ def main():
272
324
  except Exception:
273
325
  # Login with "standard" if the above fails.
274
326
  client = ITkDButils.create_client()
275
-
276
- # Check the Bustape tests
277
- try:
278
- out = BTreport(client, SN)
279
- # Upload test
280
- if out:
281
- try:
282
- db_response = client.post("uploadTestRunResults", json=out)
283
- except Exception as ex:
284
- print("Could not upload test.")
285
- print(ex)
286
-
287
327
 
288
- except Exception:
289
- print(traceback.format_exc())
328
+ # Check the Bustape tests
329
+ for SN in args.cores:
330
+ core = check_petal_core(client, SN)
331
+ if core is None:
332
+ continue
333
+
334
+ try:
335
+ out = BTreport(client, SN, petal=core)
336
+ # Upload test
337
+ if out:
338
+ try:
339
+ db_response = client.post("uploadTestRunResults", json=out)
340
+ except Exception as ex:
341
+ print("Could not upload test for {}.".format(SN))
342
+ print(ex)
343
+
344
+ except KeyError as ex:
345
+ print("Key error: {}".format(ex))
346
+
347
+ except Exception:
348
+ print(traceback.format_exc())
290
349
 
291
350
  try:
292
351
  dlg.die()
293
352
 
294
353
  except Exception:
295
354
  print("Bye !")
296
-
355
+
297
356
  if __name__ == "__main__":
298
357
  main()
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """GUI for the BTtest."""
3
3
  import dateutil.parser
4
+ import getpass
4
5
  from itkdb_gtk import ITkDButils
5
6
  from itkdb_gtk import dbGtkUtils
6
7
  from itkdb_gtk import ITkDBlogin
@@ -156,7 +157,7 @@ class BusTapeReport(dbGtkUtils.ITkDBWindow):
156
157
  bt_sn,
157
158
  complain_func=dbGtkUtils.complain)
158
159
 
159
- values = [btype, child_sn, cstage]
160
+ values = [btype, bt_sn, cstage]
160
161
 
161
162
  self.outDB = CheckBTtests.BTreport(self.session, SN, complain_func=dbGtkUtils.complain)
162
163
 
petal_qc/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """petal_qc python module."""
2
- __version__ = "0.0.16"
2
+ __version__ = "0.0.18"
3
3
 
4
4
 
5
5
  def coreMetrology():
@@ -23,7 +23,7 @@ def coreThermal():
23
23
  main()
24
24
 
25
25
  def bustapeReport():
26
- """Launches the Core metrology analysis ahd PDB script."""
26
+ """Creates the bustape report and uplades to PDB."""
27
27
  from .BTreport.CheckBTtests import main
28
28
  # from .BTreport.bustapeReport import main
29
29
  main()
@@ -9,7 +9,7 @@ from argparse import ArgumentParser
9
9
  from pathlib import Path
10
10
  try:
11
11
  import itkdb_gtk
12
-
12
+
13
13
  except ImportError:
14
14
  cwd = Path(__file__).parent.parent
15
15
  sys.path.append(cwd.as_posix())
@@ -40,31 +40,31 @@ def petalCoreTest(session, options):
40
40
  if options.institute:
41
41
  payload["filterMap"]["currentLocation"] = options.institute
42
42
  suff = options.institute
43
-
43
+
44
44
  core_list = session.get("listComponents", json=payload)
45
45
  core_tests = ["PETAL_METROLOGY_FRONT", "PETAL_METROLOGY_BACK", "XRAYIMAGING", "THERMAL_EVALUATION", "BTTESTING"]
46
-
46
+
47
47
  do_check_stage = "AT_QC_SITE"
48
48
  #do_check_stage = None
49
49
  petal_id_db = {}
50
-
50
+
51
51
  has_list = len(options.cores) != 0
52
-
52
+
53
53
  for core in core_list:
54
54
  SN = core["serialNumber"]
55
55
  altid = core['alternativeIdentifier']
56
56
  if "PPC" not in altid:
57
57
  continue
58
-
58
+
59
59
  R = r_petal_id.search(altid)
60
60
  if R is None:
61
61
  continue
62
62
 
63
63
  pid = int(R.group(1))
64
-
64
+
65
65
  if has_list and pid not in options.cores:
66
66
  continue
67
-
67
+
68
68
  petal_id_db[altid] = SN
69
69
  location = core["currentLocation"]['code']
70
70
  coreStage = core["currentStage"]['code']
@@ -88,11 +88,11 @@ def petalCoreTest(session, options):
88
88
  T = session.get("getTestRun", json={"testRun": tst["id"]})
89
89
  if T["state"] != "ready":
90
90
  print(T)
91
-
91
+
92
92
  print("-- {} [{}]".format(T["testType"]["name"], T["runNumber"]))
93
93
  if not T["passed"]:
94
94
  print("\t## test FAILED")
95
-
95
+
96
96
  for D in T["defects"]:
97
97
  print("\t{} - {}".format(D["name"], D["description"]))
98
98
 
@@ -106,7 +106,7 @@ def main():
106
106
  parser.add_argument("--cores", dest="cores", action=RangeListAction, default=[],
107
107
  help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
108
108
  options = parser.parse_args()
109
-
109
+
110
110
  # ITk_PB authentication
111
111
  dlg = ITkDBlogin.ITkDBlogin()
112
112
  session = dlg.get_client()
@@ -118,7 +118,7 @@ def main():
118
118
  print(E)
119
119
 
120
120
  dlg.die()
121
-
122
- if __name__ == "__main__":
123
- main()
124
121
 
122
+ if __name__ == "__main__":
123
+ main()
124
+
@@ -111,6 +111,11 @@ def mitutoyo2cvs(infiles, ofile, label='\\w+', data_type="Punto", keep=False, fi
111
111
  while len(line_data) < fill:
112
112
  line_data.append(0.0)
113
113
 
114
+ else:
115
+ if len(line_data)<3:
116
+ print("Warning: less than three data points: {}".format(','.join([str(v) for v in line_data])))
117
+ continue
118
+
114
119
  slin = ','.join([str(v) for v in line_data])
115
120
  fout.write(slin)
116
121
  if keep:
@@ -56,7 +56,7 @@ def do_analysis(fnam, prefix, SN, options):
56
56
  def analyze_files(ifile, options):
57
57
  """Main entry."""
58
58
  failed_files = []
59
- with open(ifile, 'r', encoding='UTF-8') as inp:
59
+ with open(ifile, 'r', encoding='ISO-8859-1') as inp:
60
60
 
61
61
  for line in inp:
62
62
  line = line.strip()
@@ -12,10 +12,10 @@ gi.require_version("Gtk", "3.0")
12
12
  from gi.repository import Gtk, Gio
13
13
 
14
14
  try:
15
- import itkdb_gtk
15
+ import petal_qc
16
16
 
17
17
  except ImportError:
18
- cwd = Path(__file__).parent.parent
18
+ cwd = Path(__file__).parent.parent.parent
19
19
  sys.path.append(cwd.as_posix())
20
20
 
21
21
  from itkdb_gtk import ITkDBlogin, ITkDButils, dbGtkUtils
@@ -271,7 +271,7 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
271
271
  self.btnFAT.unselect_all()
272
272
  self.btn_state.set_label("Undef")
273
273
  dbGtkUtils.set_button_color(self.btn_state, "azure", "black")
274
-
274
+
275
275
 
276
276
  def create_test_window(self, test_json, test_name, label):
277
277
  """Create the dialog for a DB test and add it to the notebook.
@@ -0,0 +1,57 @@
1
+ """List shipments."""
2
+ import sys
3
+ from pathlib import Path
4
+ import numpy as np
5
+
6
+ from itkdb_gtk import ITkDBlogin, ITkDButils
7
+
8
+
9
+ def main(session):
10
+ """List shipments from AVS to CERN and IFIC containing CORES."""
11
+
12
+ payload = {
13
+ "filterMap": {
14
+ "sender": "AVS",
15
+ "recipient": ["CERN", "IFIC"],
16
+ "status": "delivered"
17
+ }
18
+ }
19
+ shpmts = session.get("listShipmentsByInstitution", json=payload)
20
+ for s in shpmts:
21
+ items = session.get("listShipmentItems", json={"shipment": s["id"]})
22
+ cores = []
23
+ for it in items:
24
+ if it["component"]["componentType"]['code'] == "CORE_PETAL":
25
+ if "PPC." in it["component"]["alternativeIdentifier"]:
26
+ cores.append(it["component"]["alternativeIdentifier"])
27
+
28
+ if len(cores) == 0:
29
+ continue
30
+
31
+ print("Shipment {}".format(s["name"]))
32
+ print("AVS -> {}".format(s["recipient"]["code"]))
33
+ print(":> {}".format(s["sentTs"]))
34
+ for c in cores:
35
+ print("\t{}".format(c))
36
+
37
+ print("\n")
38
+
39
+ if __name__ == "__main__":
40
+ # ITk_PB authentication
41
+ dlg = ITkDBlogin.ITkDBlogin()
42
+ client = dlg.get_client()
43
+
44
+ try:
45
+ main(client)
46
+ # the_test = analyze_avs_metrology(client, "20USEBC1000124", "PPC.015")
47
+ #rc = ITkDButils.upload_test(client, the_test, check_runNumber=True)
48
+ #if rc:
49
+ # print(rc)
50
+
51
+ except Exception as E:
52
+ print(E)
53
+
54
+ dlg.die()
55
+
56
+
57
+
@@ -4,6 +4,7 @@ import sys
4
4
  from pathlib import Path
5
5
  import numpy as np
6
6
  import matplotlib.pyplot as plt
7
+ from argparse import ArgumentParser
7
8
 
8
9
  try:
9
10
  import petal_qc
@@ -14,7 +15,7 @@ except ImportError:
14
15
 
15
16
  from itkdb_gtk import ITkDBlogin
16
17
  import petal_qc.utils.docx_utils as docx_utils
17
-
18
+ from petal_qc.utils.ArgParserUtils import RangeListAction
18
19
 
19
20
 
20
21
  def get_value(results, code):
@@ -171,7 +172,7 @@ def plot_weighing(weights, tick_labels, document, show_total=False):
171
172
  ax.legend(loc="upper left", ncol=4)
172
173
 
173
174
 
174
- def main(session):
175
+ def main(session, options):
175
176
  """Entry point"""
176
177
  # find all cores
177
178
  # Now all the objects
@@ -206,6 +207,10 @@ def main(session):
206
207
  altid = core['alternativeIdentifier']
207
208
  if "PPC" not in altid:
208
209
  continue
210
+
211
+ pID = int(altid[4:])
212
+ if len(options.cores)>0 and pID not in options.cores:
213
+ continue
209
214
 
210
215
  petal_ids.append(altid)
211
216
  location = core["currentLocation"]['code']
@@ -314,9 +319,14 @@ def main(session):
314
319
 
315
320
  if __name__ == "__main__":
316
321
  # ITk_PB authentication
322
+ parser = ArgumentParser()
323
+ parser.add_argument("--cores", dest="cores", action=RangeListAction, default=[],
324
+ help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
325
+
326
+
317
327
  dlg = ITkDBlogin.ITkDBlogin()
318
328
  session = dlg.get_client()
319
329
 
320
- main(session)
330
+ main(session, options)
321
331
 
322
332
  dlg.die()
@@ -19,7 +19,8 @@ from petal_qc.thermal import IRBFile
19
19
 
20
20
 
21
21
  options = IRPetalParam()
22
- options.files = [Path("~/tmp/thermal/PPC.008.irb").expanduser().resolve()]
22
+ options.institute = "IFIC"
23
+ options.files = [Path("~/tmp/thermal/IFIC-thermal/IRB_files/PPC.008.irb").expanduser().resolve()]
23
24
  getter = IRDataGetter.factory(options.institute, options)
24
25
  DB = ReadGraphana("localhost")
25
26
  irbf = IRBFile.open_file(options.files)
@@ -27,6 +27,7 @@ class IRPetalParam(object):
27
27
  self.rotate = True # Rotate to have a vertical petal in mirror image
28
28
  self.debug = False # To debug
29
29
  self.report = False #
30
+ self.graphana = None # Graphana server
30
31
 
31
32
  if values is not None:
32
33
  self.set_values(values)
@@ -61,6 +62,7 @@ class IRPetalParam(object):
61
62
  help="Either IFIC or DESY to treat the different files")
62
63
  parser.add_argument("--thrs", type=float, default=P.thrs, help="Temperature threshold")
63
64
  parser.add_argument("--tco2", type=float, default=P.tco2, help="CO2 Inlet temperature")
65
+ parser.add_argument("--graphana", type=str, default=None, help="Graphana server.")
64
66
  parser.add_argument("--gauss_size", type=int, default=P.gauss_size, help="Radius of gausian filtering")
65
67
  parser.add_argument("--distance", type=float, default=P.distance, help="Distance in contour beteween slices")
66
68
  parser.add_argument("--npoints", type=int, default=P.npoints, help="Number of points per segment")
@@ -8,7 +8,6 @@ from pathlib import Path
8
8
  import matplotlib.path as mplPath
9
9
  import matplotlib.pyplot as plt
10
10
  import numpy as np
11
- import numpy.linalg as linalg
12
11
  from scipy.optimize import least_squares
13
12
 
14
13
  from petal_qc.thermal import contours
@@ -43,6 +42,9 @@ class PipeFit(object):
43
42
  self.bounds = [[-math.pi, 0.8, 0.8, -np.inf, -np.inf],
44
43
  [math.pi, 3.0, 3.0, np.inf, np.inf]]
45
44
 
45
+ self.core_center = None
46
+ self.core_band = None
47
+
46
48
  def set_front(self, is_front=True):
47
49
  """Sets for a front image.
48
50
 
@@ -119,6 +121,7 @@ class PipeFit(object):
119
121
  """
120
122
  DB = np.load(pipe_file)
121
123
  sensors = []
124
+ pipe = []
122
125
  for key, val in DB.items():
123
126
  if key == "pipe":
124
127
  pipe = val
@@ -213,7 +216,7 @@ class PipeFit(object):
213
216
  print("Center {:5.3f}, {:5.3f}".format(M[5], M[6]))
214
217
 
215
218
  @staticmethod
216
- def get_data_center(data, fraction=0.5, y0=None):
219
+ def get_data_center(data, fraction=0.5, y0=None, min_pts=5):
217
220
  """Compute the data center.
218
221
 
219
222
  Assumes it is in the half height, and the X is the average of the points
@@ -221,19 +224,19 @@ class PipeFit(object):
221
224
  """
222
225
  if y0 is None:
223
226
  bounding_box = contours.contour_bounds(data)
224
- y0 = fraction*(bounding_box[1]+bounding_box[3])
227
+ y0 = bounding_box[1] + fraction*(bounding_box[3]-bounding_box[1])
225
228
 
226
229
  window = 10
227
230
  while True:
228
231
  stripe = data[np.abs(data[:, 1] - y0) < window]
229
- if len(stripe) > 5:
232
+ if len(stripe) > min_pts:
230
233
  break
231
234
 
232
235
  window += 1
233
236
 
234
237
  m0 = np.mean(stripe, axis=0)
235
238
  center = np.array([m0[0], y0])
236
- return center
239
+ return center, (np.min(stripe[:, 0]), np.max(stripe[:, 0]))
237
240
 
238
241
  @staticmethod
239
242
  def guess_pipe_type(data, fraction=0.25) -> int:
@@ -256,7 +259,7 @@ class PipeFit(object):
256
259
 
257
260
  D = data[:, 0:2] - P0
258
261
  m0 = np.mean(D, axis=0)
259
- center = PipeFit.get_data_center(D, y0=m0[1])
262
+ center, _ = PipeFit.get_data_center(D, y0=m0[1])
260
263
  # fig, ax = plt.subplots(1,1)
261
264
  # ax.plot(D[:,0], D[:, 1], 'o', label="Data")
262
265
  # ax.plot(center[0], center[1], '*', label="Center")
@@ -273,9 +276,16 @@ class PipeFit(object):
273
276
  @staticmethod
274
277
  def guess_pipe_angle(data, center):
275
278
  """Get an estimation of th epipe angle."""
276
- c1 = PipeFit.get_data_center(data, 0.6)
277
- delta = c1 - center
278
- angle = math.atan(delta[0]/delta[1])
279
+ c1, _ = PipeFit.get_data_center(data, 0.)
280
+ delta = np.abs(c1 - center)
281
+ angle = math.atan(delta[1]/delta[0])
282
+ while angle<0:
283
+ angle += 2.0*math.pi
284
+
285
+ if angle > 1.5*math.pi:
286
+ angle -= math.pi/2.0
287
+
288
+ angle = 0.5*math.pi - angle
279
289
  return angle
280
290
 
281
291
  @staticmethod
@@ -289,8 +299,11 @@ class PipeFit(object):
289
299
 
290
300
  def initial_guess(self, data):
291
301
  """Make a first guess of the transform."""
292
- Mdata = self.get_data_center(data)
302
+ Mdata, _ = self.get_data_center(data)
293
303
  theta = self.guess_pipe_angle(data, Mdata)
304
+ if self.front:
305
+ theta = -theta
306
+
294
307
  T = -Mdata
295
308
  dxd = np.amax(data, axis=0) - np.amin(data, axis=0)
296
309
  dxp = np.amax(self.cpipe, axis=0) - np.amin(self.cpipe, axis=0)
@@ -313,7 +326,11 @@ class PipeFit(object):
313
326
  def get_residuals(self, M):
314
327
  """Compute intersecting area."""
315
328
  out = self.transform_data(self.data, M)
316
- use_area = True
329
+ y_max = np.max(out[:,1])
330
+ y_min = np.min(out[:,1])
331
+
332
+ height = y_max - y_min
333
+ use_area = False
317
334
  if use_area:
318
335
  path = mplPath.Path(out)
319
336
  ngood = 0.0
@@ -327,20 +344,29 @@ class PipeFit(object):
327
344
  real_area = 100*ngood/ntot
328
345
 
329
346
  else:
330
- area = 0.0
331
- real_area = 0
347
+ area = 1.0
348
+ real_area = 1
332
349
 
333
350
  npts = len(self.data)
334
351
  D = np.zeros([npts, 2])
335
352
  ddd = np.zeros(npts)
353
+ sum_weights = 0.0
354
+ weights = np.zeros(npts)
336
355
  for i in range(npts):
337
356
  X = out[i, :]
338
357
  dst, P = contours.find_closest_point(X[0], X[1], self.cpipe)
339
358
  D[i, :] = P - X
340
359
  ddd[i] = dst
360
+ W = 1 + 1.6*(y_max - X[1])/height
361
+ weights[i] = W
362
+ sum_weights += W
341
363
 
342
364
  # return value
343
- res = D.flatten()*area
365
+ if use_area:
366
+ res = D.flatten()*area
367
+
368
+ else:
369
+ res = np.dot(ddd, weights)/sum_weights
344
370
 
345
371
  if self.debug:
346
372
  dbg_ax. clear()
@@ -420,14 +446,17 @@ class PipeFit(object):
420
446
  elif val > self.bounds[1][i]:
421
447
  val = 0.99 * self.bounds[0][i]
422
448
  M[i] = val
423
-
449
+
424
450
  if self.debug:
425
451
  print("\n** Initial guess")
426
452
  self.print_transform(M)
427
453
  else:
428
454
  M = M0
429
455
 
430
- self.data = contours.contour_simplify(data, 1.5*factor)
456
+ self.core_center, self.core_band = self.get_data_center(data)
457
+
458
+
459
+ self.data = contours.contour_simplify(data, 1.25*factor)
431
460
  # self.data = data
432
461
  verbose = 0
433
462
  if self.debug:
@@ -436,7 +465,7 @@ class PipeFit(object):
436
465
  res = least_squares(self.get_residuals, M,
437
466
  method='trf',
438
467
  # ftol=5e-16,
439
- # xtol=None,
468
+ #xtol=1.0e-10,
440
469
  # max_nfev=10000,
441
470
  # diff_step=[0.05, 0.02, 0.02, 50, 50],
442
471
  bounds=self.bounds,
@@ -551,7 +580,7 @@ def main(data_file, opts):
551
580
  ax[0].plot(PF.center[0], PF.center[1], 'o')
552
581
  ax[0].set_title("Pipe")
553
582
 
554
- center = PF.get_data_center(data)
583
+ center, _ = PF.get_data_center(data)
555
584
  ax[1].plot(data[:, 0], data[:, 1])
556
585
  ax[1].plot(center[0], center[1], 'o')
557
586
  ax[1].set_title("Data on IR")
@@ -560,7 +589,7 @@ def main(data_file, opts):
560
589
  plt.figure(fign)
561
590
  out = PF.transform_data(PF.data, R)
562
591
  aout = PF.transform_data(data, R)
563
- center = PF.get_data_center(aout)
592
+ center, _ = PF.get_data_center(aout)
564
593
  ax[2].plot(PF.pipe[:, 0], PF.pipe[:, 1])
565
594
  ax[2].plot(out[:, 0], out[:, 1], 'o')
566
595
  ax[2].plot(center[0], center[1], 'o')
@@ -175,7 +175,8 @@ def create_golden_average(files, options):
175
175
  for i in range(2):
176
176
  ax[i].plot(R.results[i].path_length, R.results[i].path_temp, label="original")
177
177
  ax[i].plot(R.golden[i].path_length, R.golden[i].path_temp, label="golden")
178
- ax[i].legend()
178
+ if options.legend:
179
+ ax[i].legend()
179
180
 
180
181
  # Create the golden object
181
182
  golden = [Petal_IR_Analysis.AnalysisResult() for i in range(2)]
@@ -216,7 +217,7 @@ def get_golden_axis(R, golden):
216
217
  R.golden.append(G)
217
218
 
218
219
 
219
- def plot_profile_and_golden(golden, core, value):
220
+ def plot_profile_and_golden(golden, core, value, show_legend=True):
220
221
  """Plot petal core and golden average.
221
222
 
222
223
  Args:
@@ -270,7 +271,9 @@ def plot_profile_and_golden(golden, core, value):
270
271
  Tmean = np.mean(Y)
271
272
  Tband = factor*abs(Tmean)/3
272
273
 
273
- ax[0].legend(ncol=4, fontsize="x-small")
274
+ if show_legend:
275
+ ax[0].legend(ncol=4, fontsize="x-small")
276
+
274
277
  ax[0].set_title("T$_{prof}$ values")
275
278
  if value.find("temp") >= 0 or value.find("_avg") >= 0:
276
279
  ax[0].set_ylim(Tmean-Tband, Tmean+Tband)
@@ -282,14 +285,16 @@ def plot_profile_and_golden(golden, core, value):
282
285
  facecolor="yellow", alpha=0.25,
283
286
  label="Acceptance band")
284
287
 
285
- ax[1].legend(ncol=4, fontsize="x-small")
288
+ if show_legend:
289
+ ax[1].legend(ncol=4, fontsize="x-small")
290
+
286
291
  ax[1].set_title("T$_{prof}$ - Golden avg.")
287
292
  if value.find("temp") >= 0 or value.find("_avg") >= 0:
288
293
  ax[1].set_ylim(-Tband, Tband)
289
294
 
290
295
  return figures
291
296
 
292
- def show_golden_average(golden, results, value):
297
+ def show_golden_average(golden, results, value, show_legend=True):
293
298
  """Create golden average.
294
299
 
295
300
  Args:
@@ -343,7 +348,9 @@ def show_golden_average(golden, results, value):
343
348
  Tband = factor*abs(Tmean)/3
344
349
  ax[0].plot(gX, gY, '-', label="Golden", linewidth=4, alpha=0.4, color="black")
345
350
 
346
- ax[0].legend(ncol=4, fontsize="x-small")
351
+ if show_legend:
352
+ ax[0].legend(ncol=4, fontsize="x-small")
353
+
347
354
  ax[0].set_title("T$_{prof}$ values")
348
355
  if value.find("temp") >= 0 or value.find("_avg") >= 0:
349
356
  ax[0].set_ylim(Tmean-Tband, Tmean+Tband)
@@ -357,7 +364,9 @@ def show_golden_average(golden, results, value):
357
364
  facecolor="yellow", alpha=0.25,
358
365
  label="Acceptance band")
359
366
 
360
- ax[1].legend(ncol=4, fontsize="x-small")
367
+ if show_legend:
368
+ ax[1].legend(ncol=4, fontsize="x-small")
369
+
361
370
  ax[1].set_title("T$_{prof}$ - Golden avg.")
362
371
  if value.find("temp") >= 0 or value.find("_avg") >= 0:
363
372
  ax[1].set_ylim(-Tband, Tband)
@@ -369,7 +378,7 @@ def compare_golden(core, golden, value):
369
378
 
370
379
  Args:
371
380
  ----
372
- core (AnalusysResolt): The petal core
381
+ core (AnalisysResult): The petal core
373
382
  golden (AnalysisResult): The golden avrage
374
383
  value (str): The name of the variable to compare
375
384
 
@@ -396,11 +405,11 @@ def compare_golden(core, golden, value):
396
405
  indx = bisect.bisect_left(gX, x, lo=(indx-1 if indx>1 else 0))
397
406
  val = gY[indx]
398
407
  diff = abs(y-val)
399
- if diff > mxval:
400
- mxval = diff
401
408
 
402
- if diff>band:
409
+ delta = abs(diff-band)/band
410
+ if diff>band and delta>0.01:
403
411
  outsiders.append(x)
412
+ mxval = max(diff, mxval)
404
413
 
405
414
  rc = mxval < band
406
415
  return rc, mxval, outsiders
@@ -439,7 +448,7 @@ def analyze_petal_cores(files, golden, options):
439
448
  cores.append(core)
440
449
  out = [{}, {}]
441
450
  for iside in range(2):
442
- for val in ("path_temp", "sensor_avg", "sensor_std"):
451
+ for val in ("path_temp", "sensor_avg"):
443
452
  out[iside][val] = compare_golden(core.results[iside], golden[iside], val)
444
453
 
445
454
  dbOut = {
@@ -488,8 +497,8 @@ def analyze_petal_cores(files, golden, options):
488
497
  "properties": {"msg": "{} > {}".format(val[1], get_acceptance_band())}
489
498
  }
490
499
  )
491
- dbOut["passed"] = (len(dbOut["defects"]) == 0)
492
- dbOut["problems"] = (len(dbOut["comments"]) > 0)
500
+ dbOut["passed"] = len(dbOut["defects"]) == 0
501
+ dbOut["problems"] = len(dbOut["comments"]) > 0
493
502
 
494
503
  if options.out is None:
495
504
  ofile = "{}-Thermal.json".format(core.coreID)
@@ -518,10 +527,10 @@ def analyze_IRCore(options, show=True):
518
527
  with open(ofile, 'w') as fp:
519
528
  json.dump(golden, fp, indent=3, cls=IRCore.NumpyArrayEncoder)
520
529
 
521
- show_golden_average(golden, results, "path_temp")
522
- show_golden_average(golden, results, "path_spread")
523
- show_golden_average(golden, results, "sensor_avg")
524
- show_golden_average(golden, results, "sensor_std")
530
+ show_golden_average(golden, results, "path_temp", options.legend)
531
+ show_golden_average(golden, results, "path_spread", options.legend)
532
+ show_golden_average(golden, results, "sensor_avg", options.legend)
533
+ show_golden_average(golden, results, "sensor_std", options.legend)
525
534
 
526
535
  else:
527
536
  if options.golden is None:
@@ -556,17 +565,17 @@ def analyze_IRCore(options, show=True):
556
565
  else:
557
566
  document = None
558
567
 
559
- F = show_golden_average(golden, cores, "path_temp")
568
+ F = show_golden_average(golden, cores, "path_temp", options.legend)
560
569
  add_figures_to_doc(document, F, "Temperature along pipe")
561
- F = show_golden_average(golden, cores, "path_spread")
570
+ F = show_golden_average(golden, cores, "path_spread", options.legend)
562
571
  add_figures_to_doc(document, F, "Spread along pipe")
563
- F = show_golden_average(golden, cores, "sensor_avg")
572
+ F = show_golden_average(golden, cores, "sensor_avg", options.legend)
564
573
  add_figures_to_doc(document, F, "Sensor avg")
565
- F = show_golden_average(golden, cores, "sensor_std")
574
+ F = show_golden_average(golden, cores, "sensor_std", options.legend)
566
575
  add_figures_to_doc(document, F, "Sensor std")
567
576
 
568
577
  if document and not hasattr(options, "no_golden_doc"):
569
- ofile = utils.output_folder(options.folder, "Compare-to-Golden.docx")
578
+ ofile = utils.output_folder(options.folder, options.comparison)
570
579
  document.save(ofile)
571
580
 
572
581
  if show:
@@ -588,9 +597,10 @@ def main():
588
597
  parser.add_argument("--prefix", default="golden", help="Prefix for figures")
589
598
  parser.add_argument("--debug", action="store_true", default=False, help="Set to debug")
590
599
  parser.add_argument("--report", action="store_true", default=False, help="Set to produce plots for report")
591
-
600
+ parser.add_argument("--no-legend", dest="legend", action="store_false", default=True, help="Do not show the legend in plots.")
592
601
  parser.add_argument("--out", default=None, help="File to store Golden.")
593
602
  parser.add_argument("--folder", default=None, help="Folder to store output files. Superseeds folder in --out")
603
+ parser.add_argument("--comparison", default="Compare-to-Golden.docx", help="Path to comparison to golden of all input files.")
594
604
 
595
605
  options = parser.parse_args()
596
606
  if len(options.files) == 0:
@@ -10,7 +10,7 @@ import sys
10
10
  import matplotlib.path as mplPath
11
11
  import numpy as np
12
12
 
13
- from petal_qc.utils.Geometry import Point
13
+ from petal_qc.utils.Geometry import Point, remove_outliers_indx
14
14
 
15
15
 
16
16
  def pldist(point, start, end):
@@ -48,9 +48,9 @@ def closest_segment_point(P, A, B):
48
48
 
49
49
  t0 = np.dot(P-A, M)/np.dot(M, M)
50
50
  C = A + t0*M
51
- d = np.linalg.norm(P-C)
51
+ dist = np.linalg.norm(P-C)
52
52
 
53
- return d, C
53
+ return dist, C
54
54
 
55
55
 
56
56
  def find_closest(x0, y0, cont, return_index=False):
@@ -170,10 +170,10 @@ def contour_simplify(C, epsilon, return_mask=False):
170
170
 
171
171
  for i in range(index + 1, last_index):
172
172
  if indices[i - global_start_index]:
173
- d = pldist(C[i], C[start_index], C[last_index])
174
- if d > dmax:
173
+ dist = pldist(C[i], C[start_index], C[last_index])
174
+ if dist > dmax:
175
175
  index = i
176
- dmax = d
176
+ dmax = dist
177
177
 
178
178
  if dmax > epsilon:
179
179
  stk.append([start_index, index])
@@ -259,7 +259,7 @@ def in_contour(x, y, C):
259
259
  return path.contains_point(x, y, C)
260
260
 
261
261
 
262
- def get_average_in_contour(img, C):
262
+ def get_average_in_contour(img, C, remove_outliers=None):
263
263
  """Gets average and std of points within contour.
264
264
 
265
265
  We are assuming here that coordinates are integers, ie,
@@ -269,6 +269,7 @@ def get_average_in_contour(img, C):
269
269
  ----
270
270
  img: The image
271
271
  C: The contour
272
+ remove_outliers: If an int,
272
273
 
273
274
  Returns
274
275
  -------
@@ -290,6 +291,11 @@ def get_average_in_contour(img, C):
290
291
  if path.contains_point([ix, iy]):
291
292
  values.append(img[iy, ix])
292
293
 
294
+ values = np.array(values)
295
+ if remove_outliers is not None and isinstance(remove_outliers, (int, float)):
296
+ indx = remove_outliers_indx(values, remove_outliers)[0]
297
+ return np.mean(values[indx]), np.std(values[indx])
298
+
293
299
  return np.mean(values), np.std(values)
294
300
 
295
301
 
@@ -360,16 +366,16 @@ def contour_eval(C, x):
360
366
 
361
367
 
362
368
  if __name__ == "__main__":
363
- C = np.loadtxt("long_contour.csv")
369
+ cntr = np.loadtxt("long_contour.csv")
364
370
 
365
- CM0 = contour_CM(C)
366
- d0, pt0 = find_closest_point(CM0[0], CM0[1], C)
371
+ CM0 = contour_CM(cntr)
372
+ d0, pt0 = find_closest_point(CM0[0], CM0[1], cntr)
367
373
 
368
- Cs = contour_simplify(C, 1.)
374
+ Cs = contour_simplify(cntr, 1.)
369
375
  CMs = contour_CM(Cs)
370
376
  ds, pts = find_closest_point(CM0[0], CM0[1], Cs)
371
377
  d = np.linalg.norm(pt0-pts)
372
- print("no. of points {}".format(len(C)))
378
+ print("no. of points {}".format(len(cntr)))
373
379
  print("no. of points {}".format(len(Cs)))
374
380
  print(d0)
375
381
  print(ds)
@@ -22,12 +22,14 @@ from petal_qc.thermal import IRCore
22
22
  from petal_qc.thermal import IRPetal
23
23
  from petal_qc.thermal import Petal_IR_Analysis
24
24
  from petal_qc.thermal import PipeFit
25
+ from petal_qc.thermal.PetalColorMaps import HighContrast
25
26
  from petal_qc.thermal.IRDataGetter import IRDataGetter
26
27
  from petal_qc.thermal.IRPetalParam import IRPetalParam
27
28
  from petal_qc.utils.readGraphana import ReadGraphana
28
29
  from petal_qc.utils.utils import output_folder
29
30
 
30
31
 
32
+
31
33
  def get_db_date(timestamp=None):
32
34
  """Convert a date string into the expected DB format.
33
35
 
@@ -82,11 +84,16 @@ def get_inlet_temp(irbf, param):
82
84
  getter = IRDataGetter.factory(param.institute, param)
83
85
 
84
86
  # TODO: get the server from thhe options
85
- server = os.getenv("GRAFANA_SERVER")
87
+ server = None
88
+ if param.graphana is not None:
89
+ server = param.graphana
90
+ else:
91
+ server = os.getenv("GRAFANA_SERVER")
92
+
86
93
  if server is None:
87
94
  DB = ReadGraphana()
88
95
  else:
89
- print("Connecting to Graphana serfer {}".format(server))
96
+ print("Connecting to Graphana server {}".format(server))
90
97
  DB = ReadGraphana(server)
91
98
 
92
99
  frames = getter.get_analysis_frame(irbf)
@@ -166,30 +173,52 @@ def create_IR_core(options):
166
173
  ordered_pipes = [None, None]
167
174
  pipe_order = [0, 0]
168
175
  all_3d_points = IRPetal.get_all_3d_points()
176
+ core_images = IRPetal.get_last_images()
169
177
  for i in range(2):
170
178
  pipe_type = PipeFit.PipeFit.guess_pipe_type(pipes[i])
171
179
  pipe_order[i] = pipe_type
180
+ if options.save_pipes:
181
+ prfx = options.alias if len(options.alias)>0 else "pipe"
182
+ ofile = output_folder(options.folder, "{}_pipe_{}.txt".format(prfx, pipe_type))
183
+ np.savetxt(ofile, pipes[i])
184
+
172
185
  PF = PipeFit.PipeFit(pipe_type)
173
186
  R = PF.fit_ex(pipes[i], factor=getter.factor)
174
187
  if options.debug or options.report:
188
+ _X = all_3d_points[i][:, 0]
189
+ _Y = all_3d_points[i][:, 1]
190
+ _Z = all_3d_points[i][:, 2]
191
+
175
192
  fig, _ = PF.plot(show_fig=False)
176
193
  __figures__["fit_{}".format(i)] = fig
177
194
 
195
+
196
+ shape = core_images[i].shape
197
+ fig_size = [6.4, 0]
198
+ factor = fig_size[0]/shape[1]
199
+ fig_size[1] = shape[0] * factor
200
+ fig, ax = plt.subplots(1, 1, tight_layout=True, figsize=fig_size)
201
+ ax.imshow(core_images[i], origin='lower', cmap=HighContrast.reversed())
202
+ ax.plot(_X, _Y, 'o-', linewidth=1, markersize=10)
203
+ for s in PF.sensors:
204
+ o = PF.transform_inv(s, R)
205
+ ax.plot(o[:,0], o[:, 1], linewidth=2, color="black")
206
+
207
+ __figures__["sensors_{}".format(pipe_type)] = fig
208
+
178
209
  fig = plt.figure(tight_layout=True, figsize=(7, 6))
179
210
  fig.subplots_adjust(left=0.0, right=1.)
180
211
 
181
- ax = fig.add_subplot(1, 1, 1, projection='3d')
182
- ax.view_init(elev=90, azim=-90)
183
- _X = all_3d_points[i][:, 0]
184
- _Y = all_3d_points[i][:, 1]
185
- _Z = all_3d_points[i][:, 2]
186
- sct = ax.scatter(_X, _Y, _Z, c=_Z, marker='o', cmap=plt.cm.jet)
187
- fig.colorbar(sct, shrink=0.75, aspect=5)
212
+ ax = fig.add_subplot(1, 1, 1)
213
+ sct = ax.scatter(_X, _Y, c=_Z, marker='o', cmap=plt.cm.jet)
214
+ fig.colorbar(sct, pad=0.01, aspect=10)
188
215
  __figures__["pipe_path_{}".format(i)] = fig
189
216
 
190
217
  transforms[pipe_type] = R
191
218
  fitter[pipe_type] = PF
192
219
 
220
+
221
+
193
222
  # Reorder points in pipe contour so that first point corresponds to
194
223
  # the U-shape pipe minimum.
195
224
  pipes[i] = IRPetal.reorder_pipe_points(pipes[i], pipe_type, R)
@@ -261,6 +290,8 @@ def main():
261
290
  parser.add_argument("--alias", default="", help="Alias")
262
291
  parser.add_argument("--SN", default="", help="serial number")
263
292
  parser.add_argument("--folder", default=None, help="Folder to store output files. Superseeds folder in --out")
293
+ parser.add_argument("--no-legend", dest="legend", action="store_false", default=True, help="Do not show the legend in plots.")
294
+ parser.add_argument("--save_pipes", default=False, action="store_true", help="SAve pipe path. Output is alias_pipe-i.txt")
264
295
 
265
296
  IRPetalParam.add_parameters(parser)
266
297
 
@@ -44,7 +44,7 @@ def create_report(options):
44
44
 
45
45
  if options.golden is None:
46
46
  return core
47
-
47
+
48
48
  goldenFile = Path(options.golden).expanduser().resolve()
49
49
  if not goldenFile.exists():
50
50
  goldenFile = utils.output_folder(options.folder, options.golden)
@@ -76,13 +76,14 @@ def create_report(options):
76
76
  document.add_heading('Original image', level=1)
77
77
  document.add_picture(figures["original"], True, 14, caption="Original Thermal image.")
78
78
 
79
+ document.add_heading('Sensor Position', level=1)
80
+ document.add_picture([figures["sensors_0"], figures["sensors_1"]], True, 7.5, caption="Side 0 (left) and Side 1 (right) sensors.")
81
+
79
82
  document.add_heading('Result of Pipe Fit', level=1)
80
- document.add_picture(figures["fit_0"], True, 10, caption="Side 0 fit.")
81
- document.add_picture(figures["fit_1"], True, 10, caption="Side 1 fit.")
83
+ document.add_picture([figures["fit_0"],figures["fit_1"]], True, 7.5, caption="Side 0 fit (left) and Side 1 fit (right)")
82
84
 
83
85
  document.add_heading('Pipe Path', level=1)
84
- document.add_picture(figures["pipe_path_0"], True, 10, caption="Side 0 pipe temp.")
85
- document.add_picture(figures["pipe_path_1"], True, 10, caption="Side 1 pipe temp.")
86
+ document.add_picture([figures["pipe_path_0"], figures["pipe_path_1"]], True, 7.5, caption="Side 0 and 1 pipe temp (left, right).")
86
87
 
87
88
  options.add_attachments = True
88
89
  options.create_golden = False
@@ -151,6 +152,8 @@ def main():
151
152
  parser.add_argument("--folder", default=None, help="Folder to store output files. Superseeds folder in --out")
152
153
  parser.add_argument("--add_attachments", action="store_true", default=False, help="If true add the attachments section os DB file.")
153
154
  parser.add_argument("--golden", default=None, help="The golden to compare width")
155
+ parser.add_argument("--no-legend", dest="legend", action="store_false", default=True, help="Do not show the legend in plots.")
156
+ parser.add_argument("--save_pipes", default=False, action="store_true", help="SAve pipe path. Output is alias_pipe-i.txt")
154
157
 
155
158
 
156
159
  IRPetalParam.add_parameters(parser)
@@ -96,13 +96,13 @@ class Document(object):
96
96
  """Add page numbers."""
97
97
  add_page_number(self.doc.sections[0].footer.paragraphs[0])
98
98
 
99
- def add_picture(self, fig, center=True, size=10, caption=None):
99
+ def add_picture(self, fig_list, center=True, size=10, caption=None):
100
100
  """Add a picture in the document.
101
101
 
102
102
  Args:
103
103
  ----
104
104
  doc: the document
105
- fig : The matplotlib figure
105
+ fig : The matplotlib figure or list of figures.
106
106
  center (bool, optional): If picture will be centerd. Defaults to True.
107
107
  size (int, optional): Size of picture in cm. Defaults to 10.
108
108
  caption (str, optional): The text of the caption. Defaults to None.
@@ -112,14 +112,26 @@ class Document(object):
112
112
  Index of Figure if caption is True, otherwise -1.
113
113
 
114
114
  """
115
- png_file = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
116
- fig.savefig(png_file, dpi=300)
117
- png_file.close()
115
+
116
+ if not isinstance(fig_list, (list, tuple)):
117
+ fig_list = [fig_list]
118
+
118
119
  P = self.add_paragraph()
119
120
  if center:
120
121
  P.alignment = WD_ALIGN_PARAGRAPH.CENTER
121
122
 
122
- P.add_run().add_picture(png_file.name, width=Cm(size))
123
+ R = P.add_run()
124
+ for fig in fig_list:
125
+ png_file = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
126
+ fig.savefig(png_file, dpi=300)
127
+ png_file.close()
128
+
129
+ R.add_text("")
130
+ R.add_picture(png_file.name, width=Cm(size))
131
+
132
+ if len(fig_list)>0:
133
+ R.add_text(" ")
134
+
123
135
  rc = -1
124
136
  if caption:
125
137
  P = self.add_paragraph()
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: petal_qc
3
- Version: 0.0.16
3
+ Version: 0.0.18
4
4
  Summary: A collection of scripts for Petal CORE QC.
5
5
  Author-email: Carlos Lacasta <carlos.lacasta@cern.ch>
6
6
  Project-URL: Homepage, https://gitlab.cern.ch/atlas-itk/sw/db/itk-pdb-gtk-gui-utils
@@ -1,10 +1,10 @@
1
1
  petal_qc/PetalReceptionTests.py,sha256=cSrq4PUjdV7T16ARonhsnXWPBBRuvliTKlZwEPfgRVY,10832
2
- petal_qc/__init__.py,sha256=mRiA0sBPquFBSliofiW_tsLCf0ammzvN0iTnHSiqu30,1601
2
+ petal_qc/__init__.py,sha256=0fKeh6SADCpa5P2vbdpgv7ffPIr5pha5kqm9VmCIcaQ,1595
3
3
  petal_qc/dashBoard.py,sha256=U_UHNMca3H2ogD4a0Vpe4ZVUKEv2-xmGZQEZ9_aH0E4,4034
4
- petal_qc/getPetalCoreTestSummary.py,sha256=IekVCEBtNCRlKUu9spsh5ufq8wYzi4Cfh00xgxfT9eg,3794
5
- petal_qc/BTreport/CheckBTtests.py,sha256=CxR8lcawwhdzkBs8jZCXI6TSGPOsOEigpAND0D1O0cs,8178
4
+ petal_qc/getPetalCoreTestSummary.py,sha256=hTv4A8gcEkvCZLcy9ZkpwOevksz6LfK1Rb1-4ENlC7I,3706
5
+ petal_qc/BTreport/CheckBTtests.py,sha256=CoKTnW_7gbL42rVaBy9FnH1SEYifmgg1P5Iy253vDFk,9855
6
6
  petal_qc/BTreport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- petal_qc/BTreport/bustapeReport.py,sha256=c5VERxPm6BOgW_yN9O_bEPmCYpuwZ_Yt_I2sMVAp0-I,6895
7
+ petal_qc/BTreport/bustapeReport.py,sha256=M0EZQEh8G-65p6-gCOyZ0WlvnRbzQHXPwAWta9ZExnQ,6907
8
8
  petal_qc/metrology/Cluster.py,sha256=UtZ5q1EFb8f3qC0hEYBbhRg2pPbW_28aJX2EEMu00Ho,2105
9
9
  petal_qc/metrology/DataFile.py,sha256=PbFqy3-WSj69epV5EjhHc1GKhA8I74FmJYOXUjN0V20,1367
10
10
  petal_qc/metrology/PetalMetrology.py,sha256=ZEJnkR2vjNmbH7SChPtSsC1YNKgFwfa9YkHc1XNleK8,12333
@@ -14,11 +14,11 @@ petal_qc/metrology/analyze_locking_points.py,sha256=83f8nNgmXWClQnIG1plu3YYuxNme
14
14
  petal_qc/metrology/cold_noise.py,sha256=PuTaQ73WrQCJdE9ezS4UFmA3atwCuvM0ZsUOYu1ZIBw,3106
15
15
  petal_qc/metrology/compare_Cores.py,sha256=dP0i_C_VrM4s3i0RrI2g4ZcjRmgIHlAgodhGS87YYgw,9458
16
16
  petal_qc/metrology/comparisonTable.py,sha256=6Zmh-x0ahs28ZJQuHMrIiRcblUmTN1_-1otFSRNMPds,1743
17
- petal_qc/metrology/convert_mitutoyo.py,sha256=HdXQzFL5y7r8qXDzti91VItDQ-y6D9rEAYknn4yHwBs,5449
17
+ petal_qc/metrology/convert_mitutoyo.py,sha256=tpnB_fHBR8PpJeb7_q9foYKGNDRhJzxHNemmpfbSt8E,5650
18
18
  petal_qc/metrology/convert_smartscope.py,sha256=0vAEYn7ec4qTnLfjphj1QA6tK3vZsXyF6nYYj3jE5Yc,6174
19
19
  petal_qc/metrology/coreMetrology.py,sha256=rGzCyPqlfsnh2XUUDiykQFlRt3kkFkrQqVOhOJUNhyU,13427
20
20
  petal_qc/metrology/data2csv.py,sha256=2ttMSmfGLPIaOqZGima2dH6sdnSRAFTHlEbSOfW5ebA,1809
21
- petal_qc/metrology/do_Metrology.py,sha256=czsEqw7FaCtE_1FezKYy4uaChezJ89urlO4rT4BUzkQ,4351
21
+ petal_qc/metrology/do_Metrology.py,sha256=wA3fKJrdDLGYd0lEi8uSP9uRwQeS59nX6F4VtNnm9LM,4356
22
22
  petal_qc/metrology/flatness4nigel.py,sha256=SUHwn6pCEUWQV_62-_9-VKrmUdL4gVQcSA3aTtYq958,4071
23
23
  petal_qc/metrology/gtkutils.py,sha256=1pOTxiE2EZR9zNNNT5cOetga_4NG9DzLaqQPI4c1EzE,3372
24
24
  petal_qc/metrology/petal_flatness.py,sha256=KksOFO_ZrKM4nUDHRC-3mSm1tp5C7wkE_6f9ZiH9B70,10610
@@ -26,20 +26,21 @@ petal_qc/metrology/readAVSdata.py,sha256=6GRUac9b3iOoVoGfWr6rsNj1smsw9aT0tu5wuNu
26
26
  petal_qc/metrology/show_data_file.py,sha256=yZPcmMy-1EWWySiBBx0hNB3tPVh19bTr0PDaXSyIF4c,4057
27
27
  petal_qc/metrology/testSummary.py,sha256=0BhcEd1BPz2Mbonzi8nyZOzNSzpUqowBFNl5cVutqsk,994
28
28
  petal_qc/metrology/test_paralelism.py,sha256=_j__OdUwdXWM494_9HpGPuPHixMwwVphCcvHEfzWi_k,1981
29
- petal_qc/metrology/uploadPetalInformation.py,sha256=hfrXFPKLqv3RwFx5zQxLL3SI79SvgLEWV3mgxjGJLz8,26730
29
+ petal_qc/metrology/uploadPetalInformation.py,sha256=K2hHXmoQ-qi5HLTmFNn5jVsZDDXX88psGV-XIRgx1kA,26728
30
30
  petal_qc/test/analyzeMetrologyTable.py,sha256=_ipKV8-rXgLca5Bu3ATLZjGR5koFN4-qwpj88rgf-x0,3098
31
31
  petal_qc/test/checkAVStests.py,sha256=0xAJLazfkgfQ0ouc17fivaj69OXTiS9sali0DhH-jTs,4814
32
+ petal_qc/test/checkCoreShipments.py,sha256=d9W_uE0tMdfJGRuiiTOGyIW60SIj08QKWjd3Y8aVBi8,1554
32
33
  petal_qc/test/compare_golden.py,sha256=lG1rtYLw_PwKWrLk0VVdbnRhi7Ytu78q7PGWcYptM_8,1171
33
34
  petal_qc/test/createMetrologyFile.py,sha256=3fmHj8AlT_739sGRrKgpe_ZbGW2NUDAc6w0t7dEXWMo,2387
34
35
  petal_qc/test/createMetrologyTable.py,sha256=Dh9Mwab5geyojigVCS5mKba1EJU-4K1-ELDMZTDw4Dg,2687
35
36
  petal_qc/test/desyModuleBow.py,sha256=4RgDIVEMqzlGUVqKCjji95_JzfXtcgjK4kefKrVH9eY,3602
36
37
  petal_qc/test/findRawData.py,sha256=8wqvPILjfZZ0CKkDhOa_tcsYMwNwcKOLyaEoWfISBQY,2872
37
38
  petal_qc/test/getAVSjson.py,sha256=o8AYtyr7Vnp-enznmQ-NNiivZipmxtoVrmsfnRCl0X4,977
38
- petal_qc/test/getAVStests.py,sha256=G8-dKUujeG55v7unaQn-Pu2P1Qb7qVMOic9k5ZHLoJg,9799
39
+ petal_qc/test/getAVStests.py,sha256=GNqEpncUQdvo-qSf46ltGVeezSnHB2BQsKjApS6xomY,10285
39
40
  petal_qc/test/listPetalCoreComponents.py,sha256=7U9wokRkgeZdYZKeZdAadA32BlhVK6okInuh94hmj24,2502
40
41
  petal_qc/test/prepareDESYfiles.py,sha256=uRir2fv0oGqB6hKnIqRltDW-oLz1tR2SDvVkMVxCfKI,4106
41
42
  petal_qc/test/reportFromJSon.py,sha256=3YTuWeeVtw5pITloLlwEYbx84f6k9XC_jTBK53I4mLM,1456
42
- petal_qc/test/test_Graphana.py,sha256=fXcqHzgrfZGjSF-WoMLl96G97XjXVnynHYC-5rKw_-c,1032
43
+ petal_qc/test/test_Graphana.py,sha256=4wADxS_ObG9n4vsCvD1GwPQnx8bFUiUOS6ZwK83wTl8,1082
43
44
  petal_qc/test/test_coreThermal.py,sha256=YRPK3DGG7Tz66K4Kka3euXgUDzW_JlIqSYicMBhb96E,1516
44
45
  petal_qc/thermal/CSVImage.py,sha256=Vt2kYmUsZWkQvxcF8fDda3HO1Rb29kPQHnEoHFCqWYo,2038
45
46
  petal_qc/thermal/DESYdata.py,sha256=YAwxhnmA89uH1vZ_BjDo0VLATTGRngoBSFzYfLSJbZU,1904
@@ -48,16 +49,16 @@ petal_qc/thermal/IRBFile.py,sha256=_no8iUyuSQ41j34o3LVzUCjMYoviwjz02tsWvFsTUzA,2
48
49
  petal_qc/thermal/IRCore.py,sha256=sidf7HtrzEUcllv0E_o1Hks-2_2dl4Og_LWcwgPNRcE,3062
49
50
  petal_qc/thermal/IRDataGetter.py,sha256=S-Xaizrop_xQ2pgkvuw_HdKbrsDD84KThwgTfjRg0bQ,11579
50
51
  petal_qc/thermal/IRPetal.py,sha256=hVOD0VAKTA2xvNXbZ-TXAYHNlihNWsUkI2i9IEwQhZk,40887
51
- petal_qc/thermal/IRPetalParam.py,sha256=E4uZvk7Ne5TqoY8UHIbMmgB87vIxmYhTgISvs9ZgCt8,3674
52
+ petal_qc/thermal/IRPetalParam.py,sha256=_d0mIxM1laVK5cnM5v7X1L0SQ5dUeXB8kpBySHjfiLI,3817
52
53
  petal_qc/thermal/PetalColorMaps.py,sha256=6CvJHzRdojLHu3BROYSekHw8g_BJ1lJ_edyhovTIydU,3831
53
54
  petal_qc/thermal/Petal_IR_Analysis.py,sha256=ALIER9fLn2R26IMhPVzEDL6tlK7XNbCtRtH0y6kTaEU,3950
54
- petal_qc/thermal/PipeFit.py,sha256=MNQYk9NivBsDze6CVwE1cFdJjrqqbn8FK19436nFMVY,17575
55
+ petal_qc/thermal/PipeFit.py,sha256=8nEjpZC1mWh4-bhXzwXfjO8WkC_6hFYX0XXPjTHwNUw,18345
55
56
  petal_qc/thermal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- petal_qc/thermal/analyze_IRCore.py,sha256=HahnXkBRdeLlPt1BKSrj3UP6aDSHqDNbao_wxU-DlTg,20485
57
- petal_qc/thermal/contours.py,sha256=ampCKm4byZYKb_4eJFjIkdFIl2bqVXD2mV13d2XUWlw,8244
57
+ petal_qc/thermal/analyze_IRCore.py,sha256=-MsKGJR-5pJV93ipLau0FHQeconLhMPDuLQIT9LMWsU,21115
58
+ petal_qc/thermal/contours.py,sha256=Bx4ghZhgZ4ya1rr4CZvjpqZd9M924Vms1oEGrgllWG4,8591
58
59
  petal_qc/thermal/coreThermal.py,sha256=cLH7lOd6EF6y03LVaQUovlNs_Dcx9DCD1Erdw8aNrA0,16227
59
- petal_qc/thermal/create_IRCore.py,sha256=b1ja1VBELqadyWnugYlMp7eNfaLC_zhL8Q6slwOK0Y8,8219
60
- petal_qc/thermal/create_core_report.py,sha256=MsB-Knr2iiHReyInLEd825KSzwG7VuAHSM_2MmPlW3g,6019
60
+ petal_qc/thermal/create_IRCore.py,sha256=KUiRu8CUFUP0cUgtUCFkGPDePoylFqkV_GxzIVRJjZs,9441
61
+ petal_qc/thermal/create_core_report.py,sha256=v1GMt9U57pAYm3m91T3a7cFfN5xvpFY4vsfuBrtOYuU,6394
61
62
  petal_qc/thermal/pipe_back.npz,sha256=yooZuVYtHU541HcV6Gh_5B0BqdYAVEvYAuVvMMSY7Jc,3632
62
63
  petal_qc/thermal/pipe_front.npz,sha256=DuwruG9C2Z1rLigqWMApY4Orsf1SGUQGKy0Yan8Bk8A,3697
63
64
  petal_qc/thermal/pipe_read.py,sha256=HrAtEbf8pMhJDETzkevodiTbuprIOh4yHv6PzpRoz7Q,5040
@@ -67,12 +68,12 @@ petal_qc/utils/Geometry.py,sha256=NSz64lKNEh9ny5ZGRQ4abA1zPiJNJcGnTenTGZNNB8o,19
67
68
  petal_qc/utils/Progress.py,sha256=gCti4n2xfCcOTlAff5GchabGE5BCwavvDZYYKdbEsXU,4064
68
69
  petal_qc/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
70
  petal_qc/utils/all_files.py,sha256=4ja_DkbTYPY3gUPBAZq0p7KB9lnXZx-OCnpTHg9tm4I,1044
70
- petal_qc/utils/docx_utils.py,sha256=Eye16PF8W0mPBVdQvgFKWxPYV7-hzBgANPDZtUEjzf8,5805
71
+ petal_qc/utils/docx_utils.py,sha256=zVmSKHDVE8cUwbXxqyPtgS0z62VCFya1DWklOpO1rCQ,6067
71
72
  petal_qc/utils/fit_utils.py,sha256=3KUGWpBMV-bVDkQHWBigXot8chOpjAVBJ5H5b5dbdjk,5349
72
73
  petal_qc/utils/readGraphana.py,sha256=YVOztJC3q3P7F0I9Ggeiu6Mv9rZLKgj3clkLCU7k4i4,1918
73
74
  petal_qc/utils/utils.py,sha256=CqCsNIcEg6FQb3DN70tmqeLVLlQqsRfDzhfGevlnfBc,4035
74
- petal_qc-0.0.16.dist-info/METADATA,sha256=QUkF1QMT2oXGyq9eFvsbFLFAYcvHh1BpSBAUCxv5SME,953
75
- petal_qc-0.0.16.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
76
- petal_qc-0.0.16.dist-info/entry_points.txt,sha256=YPrZOsRBRsiKNDvsnbug0-Khj7DcN_Sdpq-tB_XjykI,505
77
- petal_qc-0.0.16.dist-info/top_level.txt,sha256=CCo1Xe6kLS79PruhsB6bk2CuL9VFtNdNpgJjYUs4jk4,9
78
- petal_qc-0.0.16.dist-info/RECORD,,
75
+ petal_qc-0.0.18.dist-info/METADATA,sha256=Fk2M9jtKoCnfHGAkGiMoxgdgzzGKQOy3dsjJNDyhf4g,953
76
+ petal_qc-0.0.18.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
77
+ petal_qc-0.0.18.dist-info/entry_points.txt,sha256=YPrZOsRBRsiKNDvsnbug0-Khj7DcN_Sdpq-tB_XjykI,505
78
+ petal_qc-0.0.18.dist-info/top_level.txt,sha256=CCo1Xe6kLS79PruhsB6bk2CuL9VFtNdNpgJjYUs4jk4,9
79
+ petal_qc-0.0.18.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (78.0.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5