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

@@ -15,8 +15,86 @@ except ImportError:
15
15
  from itkdb_gtk import ITkDBlogin, ITkDButils
16
16
 
17
17
 
18
- def do_metrology(results, M_values):
19
- pass
18
+ def get_value(results, code):
19
+ """Return the value of the test parameter."""
20
+ for param in results:
21
+ if param["code"] == code:
22
+ return param["value"]
23
+
24
+ raise KeyError
25
+
26
+ def distance(P1, P2):
27
+ """Distance between 2 points."""
28
+ P = (P2-P1)
29
+ S = np.sum(np.square(P))
30
+ D = np.sqrt(S)
31
+ return D
32
+
33
+ nominal_values = {
34
+ "LOCATOR1": np.array([0, -3]),
35
+ "LOCATOR2": np.array([127.916, 589.618]),
36
+ "LOCATOR3": np.array([127.916, 589.618]),
37
+ "FIDUCIAL1": np.array([0, 0]),
38
+ "FIDUCIAL2": np.array([131.104, 586.526]),
39
+ }
40
+
41
+ def get_pos(results, obj):
42
+ """Return position."""
43
+ try:
44
+ X = get_value(results, "{}_X".format(obj))
45
+ Y = get_value(results, "{}_Y".format(obj))
46
+
47
+ if abs(X) > 1000:
48
+ X /= 1000
49
+ if abs(Y)>1000:
50
+ Y /= 1000
51
+ except KeyError:
52
+ X = 0.0
53
+ Y = 0.0
54
+
55
+ P = np.array([X, Y], dtype="float64")
56
+ return P
57
+
58
+ def distance_to_nominal(results, obj):
59
+ """Return position of given locator or fiducial."""
60
+ P = get_pos(results, obj)
61
+ N = nominal_values[obj]
62
+ D = distance(P, N)
63
+ if abs(D-3)<0.5:
64
+ P[1] -= 3
65
+ D = distance(P, N)
66
+ return D
67
+
68
+ def do_metrology(results, M_values, Mould_values):
69
+ """Accumulate metrology values."""
70
+ points = ["LOCATOR1", "LOCATOR2", "LOCATOR3", "FIDUCIAL1", "FIDUCIAL2"]
71
+ coord = {}
72
+ for P in points:
73
+ coord[P] = get_pos(results, P)
74
+
75
+ fd1 = np.array(coord["FIDUCIAL1"], dtype="float64")
76
+ if fd1[0]!=0.0 or fd1[1]!=0:
77
+ for V in coord.values():
78
+ V -= fd1
79
+
80
+ for O, P in coord.items():
81
+ D = distance(P, nominal_values[O])
82
+ if D<1.0:
83
+ M_values.setdefault(O, []).append(D)
84
+ Mould_values.setdefault(O, []).append(D)
85
+
86
+ else:
87
+ print("Possibly wrong data in FAT: {} D={:.3f}".format(O, D))
88
+
89
+ def do_manufacturing(T):
90
+ """Return mould."""
91
+ mould_id = None
92
+ for prop in T["properties"]:
93
+ if prop["code"] == "MOULD_ID":
94
+ mould_id = prop["value"]
95
+ break
96
+
97
+ return mould_id
20
98
 
21
99
  def do_weighing(results, weights):
22
100
  """Accumulates weighing values to produce stack plot.
@@ -30,10 +108,27 @@ def do_weighing(results, weights):
30
108
  weights.setdefault(value["code"][ipos+1:], []).append(value["value"])
31
109
 
32
110
 
111
+ def plot_metrology(M_values, Mould_values, petal_ids):
112
+ """Plot metrology values."""
113
+ for key, values in M_values.items():
114
+ fig, ax = plt.subplots(ncols=1, nrows=1, tight_layout=True)
115
+ ax.hist(values, bins=15, range=(0, 0.150))
116
+ ax.set_title(key)
117
+
118
+ for obj in M_values.keys():
119
+ fig, ax = plt.subplots(ncols=1, nrows=4, tight_layout=True)
120
+ fig.suptitle("{} - Mould".format(obj))
121
+ for mould, m_values in Mould_values.items():
122
+ im = int(mould) - 1
123
+ ax[im].hist(m_values[obj], bins=15, range=(0, 0.150), label="Mould {}".format(mould))
124
+
125
+ for i in range(4):
126
+ ax[i].set_title("Mould {}".format(i+1))
127
+
33
128
  def plot_weighing(weights, tick_labels, show_total=False):
34
129
  """Make the plot of weights."""
35
- labels = ["COOLINGLOOPASSEMBLY", "LOCATOR_A", "LOCATOR_B", "LOCATOR_C",
36
- "HONEYCOMBSET", "FACING_FRONT", "FACING_BACK",
130
+ labels = ["COOLINGLOOPASSEMBLY", "LOCATOR_A", "LOCATOR_B", "LOCATOR_C",
131
+ "HONEYCOMBSET", "FACING_FRONT", "FACING_BACK",
37
132
  "EPOXYADHESIVE", "EPOXYPUTTY", "EPOXYCONDUCTIVE"]
38
133
 
39
134
  fig = plt.figure(tight_layout=True)
@@ -55,7 +150,7 @@ def plot_weighing(weights, tick_labels, show_total=False):
55
150
  ax.plot(X, [275.0 for x in range(npoints)], linestyle="dashed", color="black", linewidth=1,)
56
151
 
57
152
 
58
- ax.legend(loc="upper left", ncol=3, fontsize="x-small")
153
+ ax.legend(loc="upper left", ncol=4)
59
154
 
60
155
 
61
156
  def main(session):
@@ -74,27 +169,34 @@ def main(session):
74
169
  }
75
170
 
76
171
  core_list = session.get("listComponents", json=payload)
77
- core_tests = ["METROLOGY_AVS", "WEIGHING"]
172
+ core_tests = ["METROLOGY_AVS", "WEIGHING", "MANUFACTURING"]
78
173
 
79
174
  weights = {}
80
175
  petal_ids = []
81
- M_values = []
176
+ M_values = {}
177
+ Mould_values = {}
178
+ mould_id = None
82
179
  for core in core_list:
83
180
  SN = core["serialNumber"]
84
181
  altid = core['alternativeIdentifier']
85
182
  if "PPC" not in altid:
86
183
  continue
87
184
 
88
- if altid in ["PPC.016", "PPC.017"]:
89
- pass
90
-
91
185
  petal_ids.append(altid)
92
-
93
186
  location = core["currentLocation"]['code']
94
187
  coreStage = core["currentStage"]['code']
95
188
 
96
189
  print("\nPetal {} [{}] - {}. {}".format(SN, altid, coreStage, location))
97
- test_list = session.get("listTestRunsByComponent", json={"filterMap":{"serialNumber": SN, "state": "ready", "testType":core_tests}})
190
+ test_list = session.get(
191
+ "listTestRunsByComponent",
192
+ json={
193
+ "filterMap": {
194
+ "serialNumber": SN,
195
+ "state": "ready",
196
+ "testType": core_tests,
197
+ }
198
+ },
199
+ )
98
200
 
99
201
  good_tests = {}
100
202
  for tst in test_list:
@@ -114,30 +216,37 @@ def main(session):
114
216
  else:
115
217
  good_tests[ttype] = T
116
218
 
219
+ mould_desc = do_manufacturing(good_tests["MANUFACTURING"])
220
+ pos = mould_desc.rfind('.')
221
+ mould_id = mould_desc[pos+1:]
222
+ if mould_id not in Mould_values:
223
+ Mould_values[mould_id] = {}
224
+
117
225
  for ttype, T in good_tests.items():
118
226
 
119
227
  if ttype == "WEIGHING":
120
228
  do_weighing(T["results"], weights)
121
229
 
122
230
  elif ttype == "METROLOGY_AVS":
123
- do_metrology(T["results"], M_values)
124
-
231
+ do_metrology(T["results"], M_values, Mould_values[mould_id])
232
+
233
+ elif ttype == "MANUFACTURING":
234
+ continue
235
+
125
236
  else:
126
237
  for value in T["results"]:
127
238
  print("\t{} - {}".format(value["code"], value["value"]))
128
239
 
240
+ if not T["passed"]:
241
+ print("## test {} FAILED".format(T["testType"]["code"]))
129
242
 
130
- if not T["passed"]:
131
- print("\t## test FAILED")
132
-
133
- print("\t+ Defects:")
134
- if len(T["defects"]):
135
- for D in T["defects"]:
136
- print("\t{} - {}".format(D["name"], D["description"]))
137
- else:
138
- print("\nNone")
243
+ if len(T["defects"]):
244
+ print("+ Defects:")
245
+ for D in T["defects"]:
246
+ print("\t{} - {}".format(D["name"], D["description"]))
139
247
 
140
248
  plot_weighing(weights, petal_ids)
249
+ plot_metrology(M_values, Mould_values, petal_ids)
141
250
  plt.show()
142
251
 
143
252
  if __name__ == "__main__":
@@ -151,4 +260,4 @@ if __name__ == "__main__":
151
260
  except Exception as E:
152
261
  print(E)
153
262
 
154
- dlg.die()
263
+ dlg.die()
@@ -52,7 +52,7 @@ def main(session):
52
52
  print("Could not change stage")
53
53
  return False
54
54
 
55
- print("Petal {} [{}] - {}. {}".format(SN, id, coreStage, location))
55
+ print("\n\nPetal {} [{}] - {}. {}".format(SN, altid, coreStage, location))
56
56
 
57
57
  test_list = session.get("listTestRunsByComponent", json={"filterMap":{"serialNumber": SN, "state": "ready", "testType":core_tests}})
58
58
 
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python3
2
+ """List petal core components."""
3
+
4
+ from itkdb_gtk import ITkDBlogin
5
+ from itkdb_gtk import ITkDButils
6
+
7
+ def get_type(child):
8
+ """Return object type.
9
+
10
+ Args:
11
+ child: object
12
+
13
+ Returns
14
+ str: object type
15
+ """
16
+ if child["type"] is not None:
17
+ comp_type = child["type"]["code"]
18
+
19
+ else:
20
+ comp_type = child["componentType"]["code"]
21
+
22
+ return comp_type
23
+
24
+
25
+ def listPetalCoreComponents(session):
26
+ """List petal core components.
27
+
28
+ Args:
29
+ session: The itkdb session
30
+ """
31
+ final_stage = {
32
+ "BT_PETAL_FRONT": "COMPLETED",
33
+ "BT_PETAL_BACK": "COMPLETED",
34
+ "COOLING_LOOP_PETAL": "CLINCORE",
35
+ "THERMALFOAMSET_PETAL": "IN_CORE"
36
+ }
37
+ # find all cores
38
+ # Now all the objects
39
+ payload = {
40
+ "filterMap": {
41
+ "componentType": ["CORE_PETAL"],
42
+ "type": ["CORE_AVS"],
43
+ "currentLocation": ["IFIC"],
44
+ },
45
+ "sorterList": [
46
+ {"key": "alternativeIdentifier", "descending": False }
47
+ ],
48
+ }
49
+ core_list = session.get("listComponents", json=payload)
50
+
51
+ for core in core_list:
52
+ SN = core["serialNumber"]
53
+ altid = core['alternativeIdentifier']
54
+ if "PPC" not in altid:
55
+ continue
56
+
57
+
58
+ location = core["currentLocation"]['code']
59
+ coreStage = core["currentStage"]['code']
60
+ print("\n\nPetal {} [{}] - {}. {}".format(SN, altid, coreStage, location))
61
+
62
+ for child in core["children"]:
63
+ obj = ITkDButils.get_DB_component(session, child["component"])
64
+ child_type = get_type(obj)
65
+ child_stage = obj["currentStage"]["code"]
66
+ child_sn = obj["serialNumber"]
67
+ print("+-- {}: {} [{}]".format(child_sn, child_type, child_stage))
68
+ if child_stage != final_stage[child_type]:
69
+ print("Updating child stage.")
70
+ rc = ITkDButils.set_object_stage(session, child_sn, final_stage[child_type])
71
+ if rc is None:
72
+ print("Could not set final stage of {} [{}]".format(child_type, child_sn))
73
+
74
+
75
+ if __name__ == "__main__":
76
+ # ITk PDB authentication
77
+ dlg = None
78
+ try:
79
+ # We use here the Gtk GUI
80
+ dlg = ITkDBlogin.ITkDBlogin()
81
+ client = dlg.get_client()
82
+
83
+ except Exception:
84
+ # Login with "standard" if the above fails.
85
+ client = ITkDButils.create_client()
86
+
87
+ listPetalCoreComponents(client)
88
+ if dlg:
89
+ dlg.die()
@@ -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)
@@ -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
- print("Image size out of range ({}x{})".format(
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
- P1 = self.palette[v2+1]
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
- irbf = IRBFile(fname)
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()
@@ -343,14 +343,28 @@ class IRDataDESY(IRDataGetter):
343
343
  nframes = -1
344
344
 
345
345
  min_T = 1e50
346
- avg_img = irbf.append_average(nframes=nframes)
347
- for img in avg_img:
348
- val = np.min(img.image)
349
- if val < min_T:
350
- min_T = val
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
353
+
354
+ i_min = irbf.nimages-1
355
+ values = self.get_IR_data(avg_img)
351
356
 
352
- i_min = irbf.nimages-1
353
- values = self.get_IR_data(avg_img)
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, images, params) -> list:
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
- for img in images:
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.set_images(images)
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
- if not irbf.has_average:
405
- irbf.append_average(nframes=5)
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
- return [v[-1] for v in irbf.file_images]
425
+ except AttributeError:
426
+ return [irbf[0].getImage(0), irbf[1].getImage(0)]
@@ -72,6 +72,12 @@ def get_all_3d_points():
72
72
  """Return all pipe path 3D points."""
73
73
  return the_3d_points
74
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
+
75
81
  def get_last_segments():
76
82
  """Return the last segments found."""
77
83
  global the_segments
@@ -12,7 +12,7 @@ class IRPetalParam(object):
12
12
  values: ArgParser or dict with user values-
13
13
 
14
14
  """
15
- self.institute = 'IFIC' # Either IFIC or DESY to treat the different files
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
@@ -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)
@@ -528,12 +528,14 @@ def analyze_IRCore(options, show=True):
528
528
  print("I need a golden file to compare with")
529
529
  sys.exit(1)
530
530
 
531
- golden_file = find_file(options.folder, options.golden)
531
+ golden_file = Path(options.golden).expanduser().resolve()
532
532
  if not golden_file.exists():
533
- print("Golden file does not exist.")
534
- sys.exit(1)
533
+ golden_file = find_file(options.folder, options.golden)
534
+ if not golden_file.exists():
535
+ print("Golden file {} does not exist.".format(options.golden))
536
+ sys.exit(1)
535
537
 
536
- with open(golden_file, 'r') as fp:
538
+ with open(golden_file, 'r', encoding="utf-8") as fp:
537
539
  J = json.load(fp)
538
540
 
539
541
  golden = [Petal_IR_Analysis.AnalysisResult() for i in range(2)]
@@ -563,7 +565,7 @@ def analyze_IRCore(options, show=True):
563
565
  F = show_golden_average(golden, cores, "sensor_std")
564
566
  add_figures_to_doc(document, F, "Sensor std")
565
567
 
566
- if document:
568
+ if document and not hasattr(options, "no_golden_doc"):
567
569
  ofile = utils.output_folder(options.folder, "Compare-to-Golden.docx")
568
570
  document.save(ofile)
569
571
 
@@ -573,7 +575,8 @@ def analyze_IRCore(options, show=True):
573
575
  return output
574
576
 
575
577
 
576
- if __name__ == "__main__":
578
+ def main():
579
+ """Main entry."""
577
580
  from argparse import ArgumentParser
578
581
  # Argument parser
579
582
  parser = ArgumentParser()
@@ -595,3 +598,6 @@ if __name__ == "__main__":
595
598
  sys.exit()
596
599
 
597
600
  analyze_IRCore(options)
601
+
602
+ if __name__ == "__main__":
603
+ main()