petal-qc 0.0.12__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/PetalReceptionTests.py +330 -0
- petal_qc/__init__.py +11 -2
- petal_qc/dashBoard.py +26 -9
- petal_qc/metrology/PetalMetrology.py +17 -17
- petal_qc/metrology/analyze_locking_points.py +4 -4
- petal_qc/metrology/compare_Cores.py +25 -4
- petal_qc/metrology/do_Metrology.py +30 -3
- petal_qc/test/createMetrologyFile.py +77 -0
- petal_qc/test/desyModuleBow.py +126 -0
- petal_qc/test/findRawData.py +92 -0
- petal_qc/test/getAVStests.py +70 -19
- petal_qc/test/getPetalCoreTestSummary.py +18 -5
- petal_qc/test/prepareDESYfiles.py +23 -8
- petal_qc/test/reportFromJSon.py +51 -0
- petal_qc/thermal/create_core_report.py +7 -3
- {petal_qc-0.0.12.dist-info → petal_qc-0.0.15.dist-info}/METADATA +4 -4
- {petal_qc-0.0.12.dist-info → petal_qc-0.0.15.dist-info}/RECORD +20 -15
- {petal_qc-0.0.12.dist-info → petal_qc-0.0.15.dist-info}/WHEEL +1 -1
- {petal_qc-0.0.12.dist-info → petal_qc-0.0.15.dist-info}/entry_points.txt +2 -0
- {petal_qc-0.0.12.dist-info → petal_qc-0.0.15.dist-info}/top_level.txt +0 -0
|
@@ -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)
|
petal_qc/test/getAVStests.py
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Analize AVS metrology tests."""
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
3
5
|
import numpy as np
|
|
4
6
|
import matplotlib.pyplot as plt
|
|
5
7
|
|
|
6
8
|
try:
|
|
7
|
-
import
|
|
9
|
+
import petal_qc
|
|
8
10
|
|
|
9
11
|
except ImportError:
|
|
10
|
-
import sys
|
|
11
|
-
from pathlib import Path
|
|
12
12
|
cwd = Path(__file__).parent.parent
|
|
13
13
|
sys.path.append(cwd.as_posix())
|
|
14
14
|
|
|
15
|
-
from itkdb_gtk import ITkDBlogin
|
|
15
|
+
from itkdb_gtk import ITkDBlogin
|
|
16
|
+
import petal_qc.utils.docx_utils as docx_utils
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
def get_value(results, code):
|
|
@@ -108,24 +110,40 @@ def do_weighing(results, weights):
|
|
|
108
110
|
weights.setdefault(value["code"][ipos+1:], []).append(value["value"])
|
|
109
111
|
|
|
110
112
|
|
|
111
|
-
def plot_metrology(M_values, Mould_values, petal_ids):
|
|
113
|
+
def plot_metrology(M_values, Mould_values, petal_ids, document):
|
|
112
114
|
"""Plot metrology values."""
|
|
115
|
+
fsize = np.zeros(2)
|
|
116
|
+
|
|
117
|
+
document.add_heading('Deviation from nominal positions', level=1)
|
|
113
118
|
for key, values in M_values.items():
|
|
114
119
|
fig, ax = plt.subplots(ncols=1, nrows=1, tight_layout=True)
|
|
115
120
|
ax.hist(values, bins=15, range=(0, 0.150))
|
|
116
121
|
ax.set_title(key)
|
|
117
|
-
|
|
122
|
+
ax.grid(True)
|
|
123
|
+
ax.set_xlabel("Distance (mm)")
|
|
124
|
+
fsize = fig.get_size_inches()
|
|
125
|
+
if key != "FIDUCIAL1":
|
|
126
|
+
document.add_picture(fig, True, 14, caption=key)
|
|
127
|
+
|
|
128
|
+
fsize[1] = fsize[0]/0.82
|
|
129
|
+
document.add_heading('Dependency with moulds', level=1)
|
|
118
130
|
for obj in M_values.keys():
|
|
119
|
-
fig, ax = plt.subplots(ncols=1, nrows=4, tight_layout=True)
|
|
131
|
+
fig, ax = plt.subplots(ncols=1, nrows=4, tight_layout=True, figsize=fsize)
|
|
120
132
|
fig.suptitle("{} - Mould".format(obj))
|
|
121
133
|
for mould, m_values in Mould_values.items():
|
|
122
134
|
im = int(mould) - 1
|
|
123
135
|
ax[im].hist(m_values[obj], bins=15, range=(0, 0.150), label="Mould {}".format(mould))
|
|
124
136
|
|
|
125
137
|
for i in range(4):
|
|
138
|
+
ax[i].grid(True)
|
|
139
|
+
ax[i].set_xlabel("Distance (mm)")
|
|
126
140
|
ax[i].set_title("Mould {}".format(i+1))
|
|
127
141
|
|
|
128
|
-
|
|
142
|
+
if obj != "FIDUCIAL1":
|
|
143
|
+
document.add_picture(fig, True, 14, caption=obj)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def plot_weighing(weights, tick_labels, document, show_total=False):
|
|
129
147
|
"""Make the plot of weights."""
|
|
130
148
|
labels = ["COOLINGLOOPASSEMBLY", "LOCATOR_A", "LOCATOR_B", "LOCATOR_C",
|
|
131
149
|
"HONEYCOMBSET", "FACING_FRONT", "FACING_BACK",
|
|
@@ -169,13 +187,19 @@ def main(session):
|
|
|
169
187
|
}
|
|
170
188
|
|
|
171
189
|
core_list = session.get("listComponents", json=payload)
|
|
172
|
-
core_tests = ["METROLOGY_AVS", "WEIGHING", "MANUFACTURING"]
|
|
190
|
+
core_tests = ["METROLOGY_AVS", "WEIGHING", "MANUFACTURING", "DELAMINATION", "GROUNDING_CHECK", "VISUAL_INSPECTION"]
|
|
173
191
|
|
|
174
192
|
weights = {}
|
|
175
193
|
petal_ids = []
|
|
176
194
|
M_values = {}
|
|
177
195
|
Mould_values = {}
|
|
178
196
|
mould_id = None
|
|
197
|
+
i = 0
|
|
198
|
+
bad_cores = {}
|
|
199
|
+
counter = {"TOTAL":0}
|
|
200
|
+
for T in core_tests:
|
|
201
|
+
counter[T]=0
|
|
202
|
+
|
|
179
203
|
for core in core_list:
|
|
180
204
|
SN = core["serialNumber"]
|
|
181
205
|
altid = core['alternativeIdentifier']
|
|
@@ -222,6 +246,7 @@ def main(session):
|
|
|
222
246
|
if mould_id not in Mould_values:
|
|
223
247
|
Mould_values[mould_id] = {}
|
|
224
248
|
|
|
249
|
+
counter["TOTAL"] += 1
|
|
225
250
|
for ttype, T in good_tests.items():
|
|
226
251
|
|
|
227
252
|
if ttype == "WEIGHING":
|
|
@@ -233,20 +258,50 @@ def main(session):
|
|
|
233
258
|
elif ttype == "MANUFACTURING":
|
|
234
259
|
continue
|
|
235
260
|
|
|
236
|
-
else:
|
|
237
|
-
|
|
238
|
-
|
|
261
|
+
# else:
|
|
262
|
+
# if T["results"]:
|
|
263
|
+
# for value in T["results"]:
|
|
264
|
+
# print("\t{} - {}".format(value["code"], value["value"]))
|
|
239
265
|
|
|
240
266
|
if not T["passed"]:
|
|
241
267
|
print("## test {} FAILED".format(T["testType"]["code"]))
|
|
268
|
+
bad_cores.setdefault(altid, []).append({ttype: T["defects"]})
|
|
269
|
+
|
|
270
|
+
else:
|
|
271
|
+
try:
|
|
272
|
+
counter[ttype] += 1
|
|
273
|
+
except KeyError:
|
|
274
|
+
pass
|
|
242
275
|
|
|
243
276
|
if len(T["defects"]):
|
|
244
277
|
print("+ Defects:")
|
|
245
278
|
for D in T["defects"]:
|
|
246
279
|
print("\t{} - {}".format(D["name"], D["description"]))
|
|
247
280
|
|
|
248
|
-
|
|
249
|
-
|
|
281
|
+
document = docx_utils.Document()
|
|
282
|
+
document.add_page_numbers()
|
|
283
|
+
document.styles['Normal'].font.name = "Calibri"
|
|
284
|
+
document.add_heading("AVS QC tests.", 0)
|
|
285
|
+
|
|
286
|
+
document.add_heading('Results', level=1)
|
|
287
|
+
document.add_paragraph("Number of bad cores: {}.".format(len(bad_cores)))
|
|
288
|
+
document.add_heading("Bad cores", level=2)
|
|
289
|
+
for key, lst in bad_cores.items():
|
|
290
|
+
p = document.add_paragraph()
|
|
291
|
+
bf = p.add_run("{}:".format(key))
|
|
292
|
+
bf.bold = True
|
|
293
|
+
bf.italic = True
|
|
294
|
+
for item in lst:
|
|
295
|
+
for ttype, defects in item.items():
|
|
296
|
+
msg = "{}:".format(ttype)
|
|
297
|
+
for D in defects:
|
|
298
|
+
msg += "\r{} - {}".format(D["name"], D["description"])
|
|
299
|
+
document.add_paragraph(msg, style="List Bullet")
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
plot_weighing(weights, petal_ids, document)
|
|
303
|
+
plot_metrology(M_values, Mould_values, petal_ids, document)
|
|
304
|
+
document.save("AVStests.docx")
|
|
250
305
|
plt.show()
|
|
251
306
|
|
|
252
307
|
if __name__ == "__main__":
|
|
@@ -254,10 +309,6 @@ if __name__ == "__main__":
|
|
|
254
309
|
dlg = ITkDBlogin.ITkDBlogin()
|
|
255
310
|
session = dlg.get_client()
|
|
256
311
|
|
|
257
|
-
|
|
258
|
-
main(session)
|
|
259
|
-
|
|
260
|
-
except Exception as E:
|
|
261
|
-
print(E)
|
|
312
|
+
main(session)
|
|
262
313
|
|
|
263
314
|
dlg.die()
|
|
@@ -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)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Prepare raw data input files from DESY so that we can use them with this code."""
|
|
3
3
|
import os
|
|
4
|
+
import sys
|
|
4
5
|
import fnmatch
|
|
5
6
|
import re
|
|
7
|
+
import shutil
|
|
6
8
|
from pathlib import Path
|
|
7
9
|
import argparse
|
|
8
10
|
|
|
@@ -51,17 +53,26 @@ def main(folder, out_folder):
|
|
|
51
53
|
folder: the input folder where to find the original files.
|
|
52
54
|
out_folder: the folder where the new fiels will be stored.
|
|
53
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))
|
|
54
63
|
outF = Path(out_folder).expanduser().resolve()
|
|
55
64
|
if not outF.exists():
|
|
65
|
+
print("creating {}".format(outF))
|
|
56
66
|
os.mkdir(outF)
|
|
57
67
|
|
|
58
68
|
rgx = re.compile(r"Project Name: (\w+)side_.*AlternativeID=PPC[-_](\d+)", re.MULTILINE|re.DOTALL)
|
|
59
69
|
petal_cores = {}
|
|
60
|
-
for fnam in all_files(
|
|
70
|
+
for fnam in all_files(inF, "*.txt"):
|
|
61
71
|
P = Path(fnam).expanduser().resolve()
|
|
72
|
+
print(P.name)
|
|
62
73
|
with open(fnam, "r", encoding="UTF-8") as ff:
|
|
63
74
|
R = rgx.search(ff.read())
|
|
64
|
-
if R:
|
|
75
|
+
if R:
|
|
65
76
|
petal_id = "PPC.{}".format(R.group(2))
|
|
66
77
|
side = R.group(1).lower()
|
|
67
78
|
if "_2D_" in P.name:
|
|
@@ -86,7 +97,7 @@ def main(folder, out_folder):
|
|
|
86
97
|
for data_type, fnam in values.items():
|
|
87
98
|
if fnam is None:
|
|
88
99
|
print("This should not happen.")
|
|
89
|
-
|
|
100
|
+
|
|
90
101
|
with open(fnam, "r", encoding="UTF-8") as ifile:
|
|
91
102
|
data += ifile.read()
|
|
92
103
|
|
|
@@ -94,10 +105,14 @@ def main(folder, out_folder):
|
|
|
94
105
|
ofile.write(data)
|
|
95
106
|
|
|
96
107
|
list_file.close()
|
|
97
|
-
|
|
108
|
+
|
|
98
109
|
if __name__ == "__main__":
|
|
99
110
|
parser = argparse.ArgumentParser()
|
|
100
|
-
parser.add_argument("--input-folder", default=None, help="Input folder")
|
|
101
|
-
parser.add_argument("--output-folder", help="Outout fodler", default=None)
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
parser.add_argument("--input-folder", dest="input", default=None, help="Input folder")
|
|
112
|
+
parser.add_argument("--output-folder", dest="output", help="Outout fodler", default=None)
|
|
113
|
+
opts = parser.parse_args()
|
|
114
|
+
if opts.input is None or opts.output is None:
|
|
115
|
+
print("I need both an input and an output folder.")
|
|
116
|
+
sys.exit(-1)
|
|
117
|
+
|
|
118
|
+
main(opts.input, opts.output)
|
|
@@ -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)
|
|
@@ -39,12 +39,19 @@ def create_report(options):
|
|
|
39
39
|
|
|
40
40
|
print("\n## {} - {}".format(options.SN, options.alias))
|
|
41
41
|
|
|
42
|
+
# Do the core analysis.
|
|
43
|
+
core = create_IR_core(options)
|
|
44
|
+
|
|
45
|
+
if options.golden is None:
|
|
46
|
+
return core
|
|
47
|
+
|
|
42
48
|
goldenFile = Path(options.golden).expanduser().resolve()
|
|
43
49
|
if not goldenFile.exists():
|
|
44
50
|
goldenFile = utils.output_folder(options.folder, options.golden)
|
|
45
51
|
goldenFile = Path(goldenFile).expanduser().resolve()
|
|
46
52
|
if not goldenFile.exists():
|
|
47
53
|
print("I need a golden file.")
|
|
54
|
+
return core
|
|
48
55
|
|
|
49
56
|
with open(goldenFile, "r", encoding='utf-8') as fp:
|
|
50
57
|
golden = golden_from_json(json.load(fp))
|
|
@@ -65,9 +72,6 @@ def create_report(options):
|
|
|
65
72
|
P = document.add_paragraph("Golden: {}".format(goldenFile.name), "Subtitle")
|
|
66
73
|
P.alignment = docx_utils.paragraph_align_center()
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
core = create_IR_core(options)
|
|
70
|
-
|
|
71
75
|
figures = get_IRcore_plots()
|
|
72
76
|
document.add_heading('Original image', level=1)
|
|
73
77
|
document.add_picture(figures["original"], True, 14, caption="Original Thermal image.")
|