petal-qc 0.0.14.dev1__py3-none-any.whl → 0.0.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of petal-qc might be problematic. Click here for more details.

petal_qc/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """petal_qc python module."""
2
- __version__ = "0.0.14.dev1"
2
+ __version__ = "0.0.15"
3
3
 
4
4
 
5
5
  def coreMetrology():
@@ -9,9 +9,14 @@ def coreMetrology():
9
9
 
10
10
  def doMetrology():
11
11
  """Launches the Core metrology analysis in the command line."""
12
- from .metrology.do_metrology import main
12
+ from .metrology.do_Metrology import main
13
13
  main()
14
14
 
15
+ def coreMetrologyTTY():
16
+ """Launches the Core metrology analysis in the command line."""
17
+ from .metrology.do_Metrology import analyze_core_metrology
18
+ analyze_core_metrology()
19
+
15
20
  def coreThermal():
16
21
  """Launches the Core thermal analysis ahd PDB script."""
17
22
  from .thermal.coreThermal import main
@@ -513,12 +513,12 @@ def locking_point_positions(positions, document=None):
513
513
  dPL2 = np.linalg.norm(positions[1, 0:2] - positions[4, 0:2])
514
514
  deltaPL1 = (nPL1-dPL1)
515
515
  deltaPL2 = (nPL2-dPL2)
516
- fPL1 = "PASSED" if abs(deltaPL1) <= 0.050 else "FAILED"
517
- fPL2 = "PASSED" if abs(deltaPL2) <= 0.050 else "FAILED"
516
+ fPL1 = "PASSED" if abs(deltaPL1) <= 0.075 else "FAILED"
517
+ fPL2 = "PASSED" if abs(deltaPL2) <= 0.075 else "FAILED"
518
518
 
519
519
  for key, val in outDB["REL_POS_DELTA"].items():
520
520
  deltaPL = np.linalg.norm(val)
521
- fPL = "PASSED" if abs(deltaPL) <= 0.050 else "FAILED"
521
+ fPL = "PASSED" if abs(deltaPL) <= 0.075 else "FAILED"
522
522
  print("Distance {}: {:.3f} mm ({})".format(key, deltaPL, fPL))
523
523
 
524
524
  if document:
@@ -559,7 +559,7 @@ def locking_point_positions(positions, document=None):
559
559
  document.add_paragraph("")
560
560
  for key, val in outDB["REL_POS_DELTA"].items():
561
561
  deltaPL = np.linalg.norm(val)
562
- fPL = "PASSED" if abs(deltaPL) <= 0.050 else "FAILED"
562
+ fPL = "PASSED" if abs(deltaPL) <= 0.075 else "FAILED"
563
563
  document.add_paragraph("Distance {}: {:.3f} mm ({})".format(key, deltaPL, fPL))
564
564
 
565
565
  return outDB
@@ -5,6 +5,7 @@ import sys
5
5
  import argparse
6
6
  import glob
7
7
  import json
8
+ import math
8
9
  from pathlib import Path
9
10
  import numpy as np
10
11
  import matplotlib.pyplot as plt
@@ -100,17 +101,22 @@ def draw_deltas(data, keys, fnam=None, title="Front", draw_text=True):
100
101
  P = [np.zeros([nfiles, 2]),
101
102
  np.zeros([nfiles, 2]),
102
103
  np.zeros([nfiles, 2])]
104
+ D = [[],[],[]]
105
+
103
106
  fig_width = 12.0
104
107
  fig_height = 1.2*fig_width/3.0
105
108
  fig, ax = plt.subplots(nrows=1, ncols=3, tight_layout=True, figsize=(fig_width, fig_height))
106
109
  fig.suptitle(title)
110
+ figb, bx = plt.subplots(nrows=1, ncols=3, tight_layout=True, figsize=(fig_width, fig_height))
111
+ figb.suptitle(title)
112
+
107
113
  for i in range(3):
108
114
  LBL = [[],[],[]]
109
115
  ax[i].set_title(keys[i])
110
116
  ax[i].set_aspect('equal', adjustable='box')
111
- ax[i].set_xlim(-100, 100)
112
- ax[i].set_ylim(-100, 100)
113
- circle = plt.Circle((0,0), 50, color="red", alpha=0.25)
117
+ ax[i].set_xlim(-150, 150)
118
+ ax[i].set_ylim(-150, 150)
119
+ circle = plt.Circle((0,0), 75, color="red", alpha=0.25)
114
120
  ax[i].add_patch(circle)
115
121
  circle = plt.Circle((0,0), 25, color="green", alpha=0.25)
116
122
  ax[i].add_patch(circle)
@@ -118,20 +124,34 @@ def draw_deltas(data, keys, fnam=None, title="Front", draw_text=True):
118
124
  ax[i].set_xlabel("X (µm)")
119
125
  ax[i].set_ylabel("Y (µm)")
120
126
  ax[i].grid()
127
+
128
+ bx[i].set_title(keys[i])
129
+ bx[i].set_xlabel("Distance (µm)")
130
+ bx[i].grid()
131
+
121
132
 
122
133
  for j, v in enumerate(data.items()):
123
134
  label, values = v
124
135
  for k in range(3):
125
136
  ky = key_table[keys[k]]
126
- P[k][j, :] = 1000*np.array(values[ky])
137
+ point = 1000*np.array(values[ky])
138
+ P[k][j, :] = point
139
+ D[k].append(math.sqrt(point[0]**2+point[1]**2))
127
140
  LBL[k].append(label.split('.')[1].lstrip('0'))
128
141
 
142
+ bx[i].hist(D[i], bins=15, range=(0, 150))
129
143
  ax[i].scatter(P[i][:,0], P[i][:,1])
130
144
  if draw_text:
131
145
  for j in range(len(LBL[i])):
132
146
  ax[i].text(P[i][j,0], P[i][j,1], LBL[i][j]) #, ha='center', va='top')
133
147
 
148
+ ofile = Path(fnam).expanduser().resolve()
149
+ print("* parent: ", ofile.parent)
150
+ print("* stem: ", ofile.stem)
151
+ bnam = ofile.parent / "{}-h.png".format(ofile.stem)
152
+ print(bnam.as_posix())
134
153
  save_figure(fig, fnam, prefix=title)
154
+ save_figure(figb, bnam, prefix=title)
135
155
 
136
156
 
137
157
  def show_positions(options):
@@ -184,6 +204,7 @@ def show_flatness(options):
184
204
  a.set_ylim(0, 1.2*max(y_lim[0][1], y_lim[1][1]))
185
205
  x_lim = a.get_xlim()
186
206
  a.fill_between(x_lim, 0, 0.050, facecolor="darkseagreen", alpha=0.1)
207
+ a.fill_between(x_lim, 0.050, 0.100, facecolor="mediumseagreen", alpha=0.1)
187
208
  if not options.no_legend:
188
209
  a.legend(ncol=3, fontsize="x-small")
189
210
 
@@ -68,6 +68,7 @@ def do_analysis(fnam, prefix, SN, options):
68
68
 
69
69
  def analyze_files(ifile, options):
70
70
  """Main entry."""
71
+ failed_files = []
71
72
  with open(ifile, 'r', encoding='UTF-8') as inp:
72
73
 
73
74
  for line in inp:
@@ -84,10 +85,26 @@ def analyze_files(ifile, options):
84
85
  except Exception:
85
86
  fnam, prefix, SN, *_ = line.split()
86
87
 
87
- do_analysis(fnam, prefix, SN, options)
88
+ try:
89
+ with open(fnam, "r", encoding="ISO-8859-1") as fin:
90
+ ss = fin.read()
91
+ if ss.find("Punto:")<0:
92
+ options.desy=True
93
+ else:
94
+ options.desy=False
95
+
96
+ do_analysis(fnam, prefix, SN, options)
97
+ print("\n\n")
98
+ except Exception as E:
99
+ failed_files.append([fnam, E])
100
+ continue
88
101
 
89
- def main():
90
- "Main entry."
102
+ if len(failed_files)>0:
103
+ for fnam, E in failed_files:
104
+ print("### Failed file {}\n{}".format(fnam, E))
105
+
106
+ def parse_options():
107
+ """Parse command line options."""
91
108
  parser = ArgumentParser()
92
109
  parser.add_argument('files', nargs='*', help="Input files")
93
110
  parser.add_argument("--prefix", dest='prefix', default=None, help="prefix telling if it is front or back.")
@@ -113,11 +130,21 @@ def main():
113
130
  print("I need an input file")
114
131
  sys.exit()
115
132
 
133
+ return options
134
+
135
+ def main():
136
+ "Main entry."
137
+ options = parse_options()
116
138
  try:
117
139
  analyze_files(options.files[0], options)
118
140
 
119
141
  except Exception:
120
142
  print(traceback.format_exc())
121
143
 
144
+ def analyze_core_metrology():
145
+ """Do a single file analysis."""
146
+ options = parse_options()
147
+ do_analysis(options.files[0], options.prefix, options.SN, options)
148
+
122
149
  if __name__ == "__main__":
123
150
  main()
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env python3
2
+ """Locates all raw data files."""
3
+
4
+ import os
5
+ import sys
6
+ import fnmatch
7
+ import re
8
+ import shutil
9
+ from pathlib import Path
10
+ import argparse
11
+
12
+ def all_files(root, patterns='*', single_level=False, yield_folders=False):
13
+ """A generator that reruns all files in the given folder.
14
+
15
+ Args:
16
+ ----
17
+ root (file path): The folder
18
+ patterns (str, optional): The pattern of the files. Defaults to '*'.
19
+ single_level (bool, optional): If true, do not go into sub folders. Defaults to False.
20
+ yield_folders (bool, optional): If True, return folders as well. Defaults to False.
21
+
22
+ Yields
23
+ ------
24
+ str: file path name
25
+
26
+ """
27
+ patterns = patterns.split(';')
28
+ for path, subdirs, files in os.walk(root):
29
+ if yield_folders:
30
+ files.extend(subdirs)
31
+
32
+ files.sort()
33
+ for name in files:
34
+ for pattern in patterns:
35
+ if fnmatch.fnmatch(name, pattern):
36
+ yield os.path.join(path, name)
37
+ break
38
+
39
+ if single_level:
40
+ break
41
+
42
+ def main(options):
43
+ """Locate raw data files in input folder and copies them in out folder
44
+
45
+ Args:
46
+ folder_in (Path): Input folder
47
+ folder_oyt (Path): Output folder
48
+ """
49
+ reg = re.compile(r"(PPC\.[0-9]+)-(\w+)")
50
+ outF = Path(options.output).expanduser().resolve()
51
+ with open(outF, "w", encoding="utf-8") as fout:
52
+ for folder_in in options.files:
53
+ inF = Path(folder_in).expanduser().resolve()
54
+ if not inF.exists():
55
+ print("Input folder does not exist. {}".format(inF))
56
+ continue
57
+
58
+ for fnam in all_files(inF, "PPC*.txt", yield_folders=False):
59
+ R = reg.search(fnam)
60
+ if R is None:
61
+ continue
62
+
63
+ petal_id = R.group(1)
64
+ side = R.group(2)
65
+ fout.write("{ifile} {pid}-{side} {pid}\n".format(ifile=fnam, side=side, pid=petal_id))
66
+
67
+
68
+ if __name__ == "__main__":
69
+ parser = argparse.ArgumentParser()
70
+ parser.add_argument('files', nargs='*', help="Input files")
71
+ parser.add_argument("--output", dest="output", help="Output file", default="out.txt")
72
+ opts = parser.parse_args()
73
+ if len(opts.files)==0:
74
+ print("I need at least one input folder")
75
+ sys.exit(-1)
76
+
77
+ main(opts)
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env python3
2
+ """Get module bow from desy metrology files"""
3
+ import sys
4
+ import re
5
+ from pathlib import Path
6
+ import matplotlib.pyplot as plt
7
+ import numpy as np
8
+ import numpy.linalg as linalg
9
+
10
+
11
+ from petal_qc.utils.all_files import all_files
12
+ from petal_qc.metrology import DataFile
13
+ from petal_qc.metrology import DataFile
14
+ from petal_qc.utils.Geometry import fit_plane
15
+ from petal_qc.utils.Geometry import project_to_plane
16
+ from petal_qc.utils.Geometry import remove_outliers_indx
17
+
18
+
19
+ rgx = "serialNo =\\s+([A-Z0-9]+)"
20
+ serial_no = re.compile(rgx)
21
+
22
+ mtype = re.compile("Project Name:\\s+([A-Za-z0-9]+)_bow")
23
+
24
+
25
+ def get_array_range(A):
26
+ """Gets mean and range of given array."""
27
+ avg = np.mean(A)
28
+ imin = np.argmin(A)
29
+ vmin = A[imin]
30
+ imax = np.argmax(A)
31
+ vmax = A[imax]
32
+ stdv = np.std(A)
33
+ return avg, stdv, [vmin, vmax], [imin, imax]
34
+
35
+
36
+
37
+ def create_bow_figure(SN, mtype, pout, width) -> plt.Figure:
38
+ """Create the sensor bow figure.
39
+
40
+ Args:
41
+ options: Program options.
42
+ pout: set of points
43
+ width: the actual bow.
44
+
45
+ Returns:
46
+ plt.Figure: The bow figure.
47
+ """
48
+ fig_bow, ax = plt.subplots(subplot_kw={'projection': '3d'})
49
+ fig_bow.suptitle(r"{}_{} - Sensor bow {:.1f} $\mu$m".format(SN, mtype, width))
50
+
51
+ zplt = 1000*pout[:, 2]
52
+ # surf = ax.plot_trisurf(pout[:, 0], pout[:, 1], zplt, cmap=plt.cm.jet, edgecolor="black", linewidths=0.2)
53
+ surf = ax.scatter(pout[:, 0], pout[:, 1], zplt, c=zplt, marker="o", edgecolor='none')
54
+ ax.set_xlabel("X")
55
+ ax.set_ylabel("Y")
56
+ ax.set_zlabel("Z")
57
+ cbar = fig_bow.colorbar(surf, shrink=0.5, aspect=5, location="left")
58
+ cbar.set_label(r"Z ($\mu$m)")
59
+ return fig_bow
60
+
61
+
62
+ def module_bow(ifile):
63
+ """Compute module bow."""
64
+ SN = None
65
+ mod_type = None
66
+ print(Path(ifile).name)
67
+ with open(ifile, "r", encoding="utf-8") as fin:
68
+ ss = fin.read()
69
+ mtx = serial_no.search(ss)
70
+ if mtx:
71
+ SN = mtx.group(1)
72
+
73
+ mtp = mtype.search(ss)
74
+ if mtp:
75
+ mod_type = mtp.group(1)
76
+
77
+ if SN is None:
78
+ return None, None, None
79
+
80
+ print("{} - {}".format(SN, mod_type))
81
+
82
+ data = DataFile.read(ifile, "(Bow|Sensor)")
83
+ if len(data) == 0:
84
+ return None, None, None
85
+
86
+ # Try to remove locator points and get the plane
87
+ indx = remove_outliers_indx(data[:, 2])
88
+ M, TM, *_ = fit_plane(data[indx], use_average=False)
89
+
90
+ # project all data to the plane
91
+ Zmean = np.mean(M[:, 2])
92
+ M[:, 2] -= Zmean
93
+
94
+ mean, stdev, rng, irng = get_array_range(M[:, 2])
95
+ width = 1000*(rng[1]-rng[0])
96
+
97
+ # Check which one is closest to the center
98
+ min2center = linalg.norm(M[irng[0], 0:2])
99
+ max2center = linalg.norm(M[irng[1], 0:2])
100
+ # If center above the top, bow negative
101
+ if max2center < min2center:
102
+ width = -width
103
+
104
+ print("Sensor bow\nAverage: {:.1f} min {:.1f} max {:.1f} rng {:.1f}\n".format(
105
+ mean, 1000*rng[0], 1000*rng[1], width))
106
+
107
+ fig_bow = create_bow_figure(SN, mod_type, M, width)
108
+ fig_bow.savefig("{}-{}-bow.png".format(SN, mod_type), dpi=300)
109
+ plt.close(fig_bow)
110
+ del fig_bow
111
+ return SN, mod_type, width
112
+
113
+
114
+ def main(folder):
115
+ """Main entry"""
116
+ fout = open("module-bow.txt", "w", encoding="utf-8")
117
+ for fnam in all_files(folder, "*.txt"):
118
+ SN, mod_type, width = module_bow(fnam)
119
+ if SN:
120
+ fout.write("{}-{} : {:.3f}\n".format(SN, mod_type, width))
121
+
122
+ fout.close()
123
+
124
+ if __name__ == "__main__":
125
+ main("/Users/lacasta/Downloads/InterposerPetal")
126
+ #main("/Users/lacasta/Downloads/kkdvk")
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """Locates all raw data files."""
3
+
4
+ import os
5
+ import sys
6
+ import fnmatch
7
+ import re
8
+ import shutil
9
+ from pathlib import Path
10
+ import argparse
11
+
12
+ def all_files(root, patterns='*', single_level=False, yield_folders=False):
13
+ """A generator that reruns all files in the given folder.
14
+
15
+ Args:
16
+ ----
17
+ root (file path): The folder
18
+ patterns (str, optional): The pattern of the files. Defaults to '*'.
19
+ single_level (bool, optional): If true, do not go into sub folders. Defaults to False.
20
+ yield_folders (bool, optional): If True, return folders as well. Defaults to False.
21
+
22
+ Yields
23
+ ------
24
+ str: file path name
25
+
26
+ """
27
+ patterns = patterns.split(';')
28
+ for path, subdirs, files in os.walk(root):
29
+ if yield_folders:
30
+ files.extend(subdirs)
31
+
32
+ files.sort()
33
+ for name in files:
34
+ for pattern in patterns:
35
+ if fnmatch.fnmatch(name, pattern):
36
+ yield os.path.join(path, name)
37
+ break
38
+
39
+ if single_level:
40
+ break
41
+
42
+ def main(folder_in, folder_out):
43
+ """Locate raw data files in input folder and copies them in out folder
44
+
45
+ Args:
46
+ folder_in (Path): Input folder
47
+ folder_oyt (Path): Output folder
48
+ """
49
+ inF = Path(folder_in).expanduser().resolve()
50
+ if not inF.exists():
51
+ print("Input folder does not exist. {}".format(inF))
52
+ return
53
+
54
+ reg = re.compile(r"(PPC\.[0-9]+).*metr")
55
+
56
+ outF = Path(folder_out).expanduser().resolve()
57
+ if not outF.exists():
58
+ os.makedirs(outF.as_posix())
59
+
60
+ list_file = open("{}/raw-data-metrology-cores.txt".format(outF.as_posix()), "w", encoding="UTF-8")
61
+ for fnam in all_files(inF, "PPC*.txt", yield_folders=False):
62
+ R = reg.search(fnam)
63
+ if R is None:
64
+ continue
65
+
66
+ petal_id = R.group(1)
67
+ if "back" in fnam:
68
+ side = "{}-back".format(petal_id)
69
+ ofile = "{}-back.txt".format(petal_id)
70
+ elif "front" in fnam:
71
+ side = "{}-front".format(petal_id)
72
+ ofile = "{}-front.txt".format(petal_id)
73
+ else:
74
+ print("Invalid file {}".format(fnam))
75
+ continue
76
+
77
+ out_name = outF / ofile
78
+ list_file.write("{} {} {}\n".format(out_name.as_posix(), side, petal_id))
79
+ shutil.copy(fnam, out_name)
80
+
81
+ list_file.close()
82
+
83
+ if __name__ == "__main__":
84
+ parser = argparse.ArgumentParser()
85
+ parser.add_argument("--input-folder", dest="input", default=None, help="Input folder")
86
+ parser.add_argument("--output-folder", dest="output", help="Outout fodler", default=None)
87
+ opts = parser.parse_args()
88
+ if opts.input is None or opts.output is None:
89
+ print("I need both an input and an output folder.")
90
+ sys.exit(-1)
91
+
92
+ main(opts.input, opts.output)
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """Get a summery of Petal core TEsts."""
3
-
3
+ import json
4
4
  try:
5
5
  import itkdb_gtk
6
6
 
@@ -14,7 +14,7 @@ from itkdb_gtk import ITkDBlogin, ITkDButils
14
14
  from itkdb_gtk.dbGtkUtils import replace_in_container, DictDialog, ask_for_confirmation
15
15
 
16
16
 
17
- def main(session):
17
+ def main(session, options):
18
18
  """Main entry point."""
19
19
 
20
20
  # find all cores
@@ -24,17 +24,23 @@ def main(session):
24
24
  #"componentType": ["BT"],
25
25
  "componentType": ["CORE_PETAL"],
26
26
  "type": ["CORE_AVS"],
27
- "currentLocation": ["IFIC"],
27
+ # "currentLocation": ["IFIC"],
28
28
  },
29
29
  "sorterList": [
30
30
  {"key": "alternativeIdentifier", "descending": False }
31
31
  ],
32
32
  }
33
+ suff = "ALL"
34
+ if options.institute:
35
+ payload["filterMap"]["currentLocation"] = options.institute
36
+ suff = options.institute
37
+
33
38
  core_list = session.get("listComponents", json=payload)
34
39
  core_tests = ["PETAL_METROLOGY_FRONT", "PETAL_METROLOGY_BACK", "XRAYIMAGING", "THERMAL_EVALUATION", "BTTESTING"]
35
40
 
36
41
  do_check_stage = "AT_QC_SITE"
37
42
  #do_check_stage = None
43
+ petal_id_db = {}
38
44
 
39
45
  for core in core_list:
40
46
  SN = core["serialNumber"]
@@ -42,7 +48,7 @@ def main(session):
42
48
  if "PPC" not in altid:
43
49
  continue
44
50
 
45
-
51
+ petal_id_db[altid] = SN
46
52
  location = core["currentLocation"]['code']
47
53
  coreStage = core["currentStage"]['code']
48
54
  if do_check_stage:
@@ -73,14 +79,21 @@ def main(session):
73
79
  for D in T["defects"]:
74
80
  print("\t{} - {}".format(D["name"], D["description"]))
75
81
 
82
+ with open("petal_ID_db_{}.json".format(suff), "w", encoding="utf-8") as fOut:
83
+ json.dump(petal_id_db, fOut, indent=3)
76
84
 
77
85
  if __name__ == "__main__":
86
+ from argparse import ArgumentParser
87
+ parser = ArgumentParser()
88
+ parser.add_argument("--institute", default=None, help="The petal current location")
89
+ options = parser.parse_args()
90
+
78
91
  # ITk_PB authentication
79
92
  dlg = ITkDBlogin.ITkDBlogin()
80
93
  session = dlg.get_client()
81
94
 
82
95
  try:
83
- main(session)
96
+ main(session, options)
84
97
 
85
98
  except Exception as E:
86
99
  print(E)
@@ -4,6 +4,7 @@ import os
4
4
  import sys
5
5
  import fnmatch
6
6
  import re
7
+ import shutil
7
8
  from pathlib import Path
8
9
  import argparse
9
10
 
@@ -52,14 +53,23 @@ def main(folder, out_folder):
52
53
  folder: the input folder where to find the original files.
53
54
  out_folder: the folder where the new fiels will be stored.
54
55
  """
56
+ inF = Path(folder).expanduser().resolve()
57
+ if not inF.exists():
58
+ print("Input folder does not exist. {}".format(inF))
59
+ return
60
+
61
+ print("Reading folder: {}".format(inF))
62
+ print("output in {}".format(out_folder))
55
63
  outF = Path(out_folder).expanduser().resolve()
56
64
  if not outF.exists():
65
+ print("creating {}".format(outF))
57
66
  os.mkdir(outF)
58
67
 
59
68
  rgx = re.compile(r"Project Name: (\w+)side_.*AlternativeID=PPC[-_](\d+)", re.MULTILINE|re.DOTALL)
60
69
  petal_cores = {}
61
- for fnam in all_files(folder, "*.txt"):
70
+ for fnam in all_files(inF, "*.txt"):
62
71
  P = Path(fnam).expanduser().resolve()
72
+ print(P.name)
63
73
  with open(fnam, "r", encoding="UTF-8") as ff:
64
74
  R = rgx.search(ff.read())
65
75
  if R:
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env python3
2
+ """List failing cores from JSon files."""
3
+ import sys
4
+ import argparse
5
+ from pathlib import Path
6
+ import json
7
+
8
+
9
+
10
+ def main(options):
11
+ """main entry."""
12
+ petal_cores = {}
13
+ for fnam in options.files:
14
+ ifile = Path(fnam).expanduser().resolve()
15
+ with open(ifile, "r", encoding="utf-8") as fin:
16
+ data = json.load(fin)
17
+
18
+ if not data["passed"]:
19
+ petalId = data["component"]
20
+ if petalId not in petal_cores:
21
+ petal_cores[petalId] = {"FRONT": [], "BACK": []}
22
+
23
+ side = "FRONT" if "FRONT" in data["testType"] else "BACK"
24
+ for D in data["defects"]:
25
+ petal_cores[petalId][side].append("{}: {}".format(D["name"], D["description"]))
26
+
27
+
28
+ keys = sorted(petal_cores.keys())
29
+ for petalId in keys:
30
+ print(petalId)
31
+ for side in ["FRONT","BACK"]:
32
+ if len(petal_cores[petalId][side])>0:
33
+ print("+-", side)
34
+ for D in petal_cores[petalId][side]:
35
+ print(" ", D)
36
+
37
+ print("\n")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ parser = argparse.ArgumentParser()
42
+ parser.add_argument('files', nargs='*', help="Input files")
43
+ opts = parser.parse_args()
44
+
45
+ from petal_qc.utils.all_files import all_files
46
+
47
+ opts.files = []
48
+ for fnam in all_files(Path("~/tmp/petal-metrology/Production/Results").expanduser(), "*.json"):
49
+ opts.files.append(fnam)
50
+
51
+ main(opts)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: petal_qc
3
- Version: 0.0.14.dev1
3
+ Version: 0.0.15
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
@@ -10,14 +10,14 @@ Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.7
11
11
  Description-Content-Type: text/markdown
12
12
  Requires-Dist: itkdb
13
- Requires-Dist: itkdb-gtk >=0.10.10
13
+ Requires-Dist: itkdb_gtk>=0.10.10
14
14
  Requires-Dist: numpy
15
15
  Requires-Dist: matplotlib
16
16
  Requires-Dist: lmfit
17
17
  Requires-Dist: openpyxl
18
18
  Requires-Dist: pandas
19
- Requires-Dist: python-dateutil
20
- Requires-Dist: python-docx
19
+ Requires-Dist: python_dateutil
20
+ Requires-Dist: python_docx
21
21
  Requires-Dist: scipy
22
22
  Requires-Dist: scikit-image
23
23
 
@@ -1,5 +1,5 @@
1
1
  petal_qc/PetalReceptionTests.py,sha256=cSrq4PUjdV7T16ARonhsnXWPBBRuvliTKlZwEPfgRVY,10832
2
- petal_qc/__init__.py,sha256=YDzaXlGm2rI4RBobKXtR84NpZJWMw8nl_C8Y5O2Vg2s,1311
2
+ petal_qc/__init__.py,sha256=vWXzH1nq_4LPfkOPhVjMfsxaexYA1nBMrVTx8Y9FSyY,1491
3
3
  petal_qc/dashBoard.py,sha256=U_UHNMca3H2ogD4a0Vpe4ZVUKEv2-xmGZQEZ9_aH0E4,4034
4
4
  petal_qc/BTreport/CheckBTtests.py,sha256=CxR8lcawwhdzkBs8jZCXI6TSGPOsOEigpAND0D1O0cs,8178
5
5
  petal_qc/BTreport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -9,15 +9,15 @@ petal_qc/metrology/DataFile.py,sha256=PbFqy3-WSj69epV5EjhHc1GKhA8I74FmJYOXUjN0V2
9
9
  petal_qc/metrology/PetalMetrology.py,sha256=YxzS-awU4PWdCYdJH754BrSOEilHf9gsyS7fcGzWV04,12781
10
10
  petal_qc/metrology/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  petal_qc/metrology/all2csv.py,sha256=KTgEGaediylwkGN7gyWyQqUjU0f9FOa3xF4z1W38EcU,1569
12
- petal_qc/metrology/analyze_locking_points.py,sha256=isIWUsZrBpXgQbmXN4Gl5Zbv5R91UC8jQAU113_gRD8,20531
12
+ petal_qc/metrology/analyze_locking_points.py,sha256=83f8nNgmXWClQnIG1plu3YYuxNmeEeTu8VKJE9izw70,20531
13
13
  petal_qc/metrology/cold_noise.py,sha256=PuTaQ73WrQCJdE9ezS4UFmA3atwCuvM0ZsUOYu1ZIBw,3106
14
- petal_qc/metrology/compare_Cores.py,sha256=ysfDs0QIqIH0BBgy5RUXZNSzCgjqLfjN2XH7MLBnRNE,7458
14
+ petal_qc/metrology/compare_Cores.py,sha256=w4BZpXoDwX9N0FMQ2_1xcpnTELbdvQyRPvvdkJc1E0M,8207
15
15
  petal_qc/metrology/comparisonTable.py,sha256=6Zmh-x0ahs28ZJQuHMrIiRcblUmTN1_-1otFSRNMPds,1743
16
16
  petal_qc/metrology/convert_mitutoyo.py,sha256=HdXQzFL5y7r8qXDzti91VItDQ-y6D9rEAYknn4yHwBs,5449
17
17
  petal_qc/metrology/convert_smartscope.py,sha256=0vAEYn7ec4qTnLfjphj1QA6tK3vZsXyF6nYYj3jE5Yc,6174
18
18
  petal_qc/metrology/coreMetrology.py,sha256=2BHc-h2xaFB3IK6VW_t96_swLiCf04EW7CeHq7hEKe4,13869
19
19
  petal_qc/metrology/data2csv.py,sha256=2ttMSmfGLPIaOqZGima2dH6sdnSRAFTHlEbSOfW5ebA,1809
20
- petal_qc/metrology/do_Metrology.py,sha256=eS8SeEn7oRiEceO3ybhSr2dv_Ki1NoKj9QAySSHmEB8,3949
20
+ petal_qc/metrology/do_Metrology.py,sha256=-2CicDzlMDo_7swiswF98RjcHjWtBhLbgnwXO_zTt9Q,4793
21
21
  petal_qc/metrology/flatness4nigel.py,sha256=SUHwn6pCEUWQV_62-_9-VKrmUdL4gVQcSA3aTtYq958,4071
22
22
  petal_qc/metrology/gtkutils.py,sha256=1pOTxiE2EZR9zNNNT5cOetga_4NG9DzLaqQPI4c1EzE,3372
23
23
  petal_qc/metrology/petal_flatness.py,sha256=JpgWlaxeLFsCZHquSUD3axCNvwtB5LOZ1wQHPUVUwc0,11052
@@ -28,11 +28,15 @@ petal_qc/metrology/test_paralelism.py,sha256=_j__OdUwdXWM494_9HpGPuPHixMwwVphCcv
28
28
  petal_qc/metrology/uploadPetalInformation.py,sha256=7JXTNRaThXlWLKwPAC6v9N2jFK1nmG5AkGJqEryMyRE,26769
29
29
  petal_qc/test/checkAVStests.py,sha256=TQ6EscfqL65sNC6QX5FElakYShnuMvqvKYhroXjZD0Q,4815
30
30
  petal_qc/test/compare_golden.py,sha256=lG1rtYLw_PwKWrLk0VVdbnRhi7Ytu78q7PGWcYptM_8,1171
31
+ petal_qc/test/createMetrologyFile.py,sha256=3fmHj8AlT_739sGRrKgpe_ZbGW2NUDAc6w0t7dEXWMo,2387
32
+ petal_qc/test/desyModuleBow.py,sha256=4RgDIVEMqzlGUVqKCjji95_JzfXtcgjK4kefKrVH9eY,3602
33
+ petal_qc/test/findRawData.py,sha256=8wqvPILjfZZ0CKkDhOa_tcsYMwNwcKOLyaEoWfISBQY,2872
31
34
  petal_qc/test/getAVSjson.py,sha256=o8AYtyr7Vnp-enznmQ-NNiivZipmxtoVrmsfnRCl0X4,977
32
35
  petal_qc/test/getAVStests.py,sha256=BMP_u7wbgSSu1bYtjDiSBWVGNOmKPJtMhG_9t9GQxB4,9516
33
- petal_qc/test/getPetalCoreTestSummary.py,sha256=5MGr0G0Lvk6ruiUxK5EmJOWv9iz-mIhxRn3WfQzjhoM,2597
36
+ petal_qc/test/getPetalCoreTestSummary.py,sha256=8eX-UPuNjARAZSaEZpNveqHP1WBFmcJnno3B36v6wpU,3159
34
37
  petal_qc/test/listPetalCoreComponents.py,sha256=7U9wokRkgeZdYZKeZdAadA32BlhVK6okInuh94hmj24,2502
35
- petal_qc/test/prepareDESYfiles.py,sha256=mvC-iQlIASm6j8B5_SbMAmmTtBwVsCAzBOn7VLUVwUc,3717
38
+ petal_qc/test/prepareDESYfiles.py,sha256=g1qSdmddk7Ope71-TvY5oztcZJ1vRqiX5UvNtZAW5TE,4034
39
+ petal_qc/test/reportFromJSon.py,sha256=3YTuWeeVtw5pITloLlwEYbx84f6k9XC_jTBK53I4mLM,1456
36
40
  petal_qc/test/test_Graphana.py,sha256=fXcqHzgrfZGjSF-WoMLl96G97XjXVnynHYC-5rKw_-c,1032
37
41
  petal_qc/test/test_coreThermal.py,sha256=YRPK3DGG7Tz66K4Kka3euXgUDzW_JlIqSYicMBhb96E,1516
38
42
  petal_qc/thermal/CSVImage.py,sha256=Vt2kYmUsZWkQvxcF8fDda3HO1Rb29kPQHnEoHFCqWYo,2038
@@ -64,8 +68,8 @@ petal_qc/utils/docx_utils.py,sha256=Eye16PF8W0mPBVdQvgFKWxPYV7-hzBgANPDZtUEjzf8,
64
68
  petal_qc/utils/fit_utils.py,sha256=3KUGWpBMV-bVDkQHWBigXot8chOpjAVBJ5H5b5dbdjk,5349
65
69
  petal_qc/utils/readGraphana.py,sha256=YVOztJC3q3P7F0I9Ggeiu6Mv9rZLKgj3clkLCU7k4i4,1918
66
70
  petal_qc/utils/utils.py,sha256=CqCsNIcEg6FQb3DN70tmqeLVLlQqsRfDzhfGevlnfBc,4035
67
- petal_qc-0.0.14.dev1.dist-info/METADATA,sha256=CPpAB40vJWj80fSWpLiG6ZhNP-oZ0V--lgqpCXz1oDM,959
68
- petal_qc-0.0.14.dev1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
69
- petal_qc-0.0.14.dev1.dist-info/entry_points.txt,sha256=1HWHVknmjrv_zXikQ60y_-qvieHungPH-EEzSimO5bw,407
70
- petal_qc-0.0.14.dev1.dist-info/top_level.txt,sha256=CCo1Xe6kLS79PruhsB6bk2CuL9VFtNdNpgJjYUs4jk4,9
71
- petal_qc-0.0.14.dev1.dist-info/RECORD,,
71
+ petal_qc-0.0.15.dist-info/METADATA,sha256=ghjcP3iMvHzI7sozmhikxxlR1zLXrvk5iACOWcrEEUc,953
72
+ petal_qc-0.0.15.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
73
+ petal_qc-0.0.15.dist-info/entry_points.txt,sha256=1DtsI43PHWiGxvmhRhUhL4G1-XYBRyfqKgNMMTiqeJA,452
74
+ petal_qc-0.0.15.dist-info/top_level.txt,sha256=CCo1Xe6kLS79PruhsB6bk2CuL9VFtNdNpgJjYUs4jk4,9
75
+ petal_qc-0.0.15.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -2,6 +2,7 @@
2
2
  analyzeIRCore = petal_qc:analyzeIRCore
3
3
  bustapeReport = petal_qc:bustapeReport
4
4
  coreMetrology = petal_qc:coreMetrology
5
+ coreMetrologyTTY = petal_qc:coreMetrologyTTY
5
6
  coreThermal = petal_qc:coreThermal
6
7
  createCoreThermalReport = petal_qc:createCoreThermalReport
7
8
  doMetrology = petal_qc:doMetrology