itkdb-gtk 0.10.9.dev3__py3-none-any.whl → 0.10.10__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 itkdb-gtk might be problematic. Click here for more details.
- itkdb_gtk/CreateShipments.py +30 -24
- itkdb_gtk/GetShipments.py +83 -81
- itkdb_gtk/GlueWeight.py +35 -51
- itkdb_gtk/ITkDBlogin.py +6 -2
- itkdb_gtk/ITkDButils.py +138 -19
- itkdb_gtk/PanelVisualInspection.py +258 -73
- itkdb_gtk/PetalReceptionTests.py +20 -11
- itkdb_gtk/SensorUtils.py +16 -14
- itkdb_gtk/ShowAttachments.py +3 -1
- itkdb_gtk/UploadModuleIV.py +8 -8
- itkdb_gtk/UploadMultipleTests.py +174 -109
- itkdb_gtk/UploadTest.py +17 -14
- itkdb_gtk/VisualInspection.py +299 -0
- itkdb_gtk/WireBondGui.py +556 -163
- itkdb_gtk/__init__.py +7 -7
- itkdb_gtk/dashBoard.py +86 -19
- itkdb_gtk/dbGtkUtils.py +79 -25
- {itkdb_gtk-0.10.9.dev3.dist-info → itkdb_gtk-0.10.10.dist-info}/METADATA +1 -1
- itkdb_gtk-0.10.10.dist-info/RECORD +28 -0
- {itkdb_gtk-0.10.9.dev3.dist-info → itkdb_gtk-0.10.10.dist-info}/WHEEL +1 -1
- {itkdb_gtk-0.10.9.dev3.dist-info → itkdb_gtk-0.10.10.dist-info}/entry_points.txt +1 -1
- itkdb_gtk/UploadPetalInformation.py +0 -711
- itkdb_gtk/readAVSdata.py +0 -693
- itkdb_gtk-0.10.9.dev3.dist-info/RECORD +0 -29
- {itkdb_gtk-0.10.9.dev3.dist-info → itkdb_gtk-0.10.10.dist-info}/top_level.txt +0 -0
itkdb_gtk/WireBondGui.py
CHANGED
|
@@ -2,26 +2,34 @@
|
|
|
2
2
|
"""Wirebonding GUI for PSB."""
|
|
3
3
|
|
|
4
4
|
import sys
|
|
5
|
+
import re
|
|
5
6
|
import json
|
|
7
|
+
import copy
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from collections import namedtuple
|
|
6
10
|
import gi
|
|
7
11
|
|
|
8
12
|
gi.require_version("Gtk", "3.0")
|
|
9
|
-
from gi.repository import Gtk, Gio,
|
|
13
|
+
from gi.repository import Gtk, Gio, Gdk
|
|
10
14
|
|
|
11
15
|
try:
|
|
12
16
|
import itkdb_gtk
|
|
13
17
|
|
|
14
18
|
except ImportError:
|
|
15
|
-
from pathlib import Path
|
|
16
19
|
cwd = Path(__file__).parent.parent
|
|
17
20
|
sys.path.append(cwd.as_posix())
|
|
18
21
|
import itkdb_gtk
|
|
19
|
-
|
|
22
|
+
|
|
20
23
|
__HELP_LINK__="https://itkdb-gtk.docs.cern.ch/wirebondTest.html"
|
|
21
24
|
|
|
22
25
|
from itkdb_gtk import dbGtkUtils
|
|
23
26
|
from itkdb_gtk import ITkDBlogin, ITkDButils, UploadTest
|
|
24
27
|
|
|
28
|
+
|
|
29
|
+
#valid_channel = re.compile("(^[0-9]+)-([0-9]+)")
|
|
30
|
+
valid_channel = re.compile("^[0-9]+[\\s*\\,\\s,-[0-9]+]*")
|
|
31
|
+
|
|
32
|
+
|
|
25
33
|
test_parameters = {
|
|
26
34
|
"Repaired Row 1": "REPAIRED_FRONTEND_ROW1",
|
|
27
35
|
"Failed Row 1": "FAILED_FRONTEND_ROW1",
|
|
@@ -84,21 +92,75 @@ module_param = {
|
|
|
84
92
|
],
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
module_to_tf = {
|
|
96
|
+
0: [],
|
|
97
|
+
1: [],
|
|
98
|
+
2: [],
|
|
99
|
+
3: [],
|
|
100
|
+
4: [],
|
|
101
|
+
5: []
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
hyb_to_pb = {
|
|
105
|
+
0: [],
|
|
106
|
+
1: [],
|
|
107
|
+
2: [],
|
|
108
|
+
3: [],
|
|
109
|
+
4: [],
|
|
110
|
+
5: []
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def range_to_list(V):
|
|
115
|
+
"""Convert a range to a list.
|
|
97
116
|
|
|
98
|
-
|
|
117
|
+
ch1-ch2 or ch1:ch2 -> [ch1, ch1+1, ch1+2, ..., ch2] or
|
|
118
|
+
ch1:step:ch2 -> [ch1, ch1+sep, ch1+2*step, ..., ch2]
|
|
119
|
+
"""
|
|
120
|
+
nfound = 0
|
|
121
|
+
for c in "-:,":
|
|
122
|
+
if c in V:
|
|
123
|
+
nfound += 1
|
|
124
|
+
break
|
|
125
|
+
|
|
126
|
+
if nfound == 0:
|
|
127
|
+
return [V]
|
|
128
|
+
|
|
129
|
+
out = []
|
|
130
|
+
values = V.split(',')
|
|
131
|
+
for V in values:
|
|
132
|
+
if '-' in V:
|
|
133
|
+
endpoints = list(map(int, V.split('-')))
|
|
134
|
+
endpoints.sort()
|
|
135
|
+
for i in range(endpoints[0], endpoints[1]+1):
|
|
136
|
+
out.append(str(i))
|
|
137
|
+
elif ':' in V:
|
|
138
|
+
endpoints = list(map(int, V.split(':')))
|
|
139
|
+
if len(endpoints) == 2:
|
|
140
|
+
endpoints.sort()
|
|
141
|
+
for i in range(endpoints[0], endpoints[1]+1):
|
|
142
|
+
out.append(str(i))
|
|
143
|
+
|
|
144
|
+
elif len(endpoints) == 3:
|
|
145
|
+
for i in range(endpoints[0], endpoints[2]+1, endpoints[1]):
|
|
146
|
+
out.append(str(i))
|
|
147
|
+
|
|
148
|
+
else:
|
|
149
|
+
print("Wring range specification. {}".format(V))
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
else:
|
|
153
|
+
out.append(V)
|
|
154
|
+
|
|
155
|
+
return out
|
|
99
156
|
|
|
100
|
-
|
|
157
|
+
def count_items(items):
|
|
158
|
+
"""Count number of channels from results."""
|
|
159
|
+
nitems = 0
|
|
160
|
+
for key in items.keys():
|
|
161
|
+
nitems += len(range_to_list(key))
|
|
101
162
|
|
|
163
|
+
return nitems
|
|
102
164
|
|
|
103
165
|
def find_holes(chan_list, min_chan=0, max_chan=999999):
|
|
104
166
|
"""Find groups of consecutive channels."""
|
|
@@ -142,19 +204,41 @@ def find_holes(chan_list, min_chan=0, max_chan=999999):
|
|
|
142
204
|
return holes
|
|
143
205
|
|
|
144
206
|
|
|
207
|
+
def wire2strip(iwire, irow, first_chan):
|
|
208
|
+
"""From bond to strip number."""
|
|
209
|
+
if irow % 2:
|
|
210
|
+
istrip = 2*(iwire-first_chan) + 1
|
|
211
|
+
else:
|
|
212
|
+
istrip = 2*(iwire-first_chan)
|
|
213
|
+
|
|
214
|
+
return istrip
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class Hole:
|
|
218
|
+
"""A range of consecutive unconnected channels."""
|
|
219
|
+
def __init__(self, *args):
|
|
220
|
+
for i, name in enumerate(['sensor', 'hybrid', 'row', 'chan', 'width']):
|
|
221
|
+
setattr(self, name, args[i])
|
|
222
|
+
|
|
223
|
+
def __repr__(self):
|
|
224
|
+
return "sensor: {} hyb: {} row: {} chan: {} width: {}".format(
|
|
225
|
+
self.sensor, self.hybrid, self.row, self.chan, self.width
|
|
226
|
+
)
|
|
227
|
+
|
|
145
228
|
class HybridHoles:
|
|
146
|
-
"""Holes in hybrid
|
|
229
|
+
"""Holes in hybrid bonds.
|
|
147
230
|
|
|
148
231
|
Holes are defined by a list [first_chan, n_chan].
|
|
149
232
|
"""
|
|
150
233
|
|
|
151
|
-
def __init__(self, param, hid=0):
|
|
234
|
+
def __init__(self, param, win=None, hid=0):
|
|
152
235
|
"""Initialization.
|
|
153
236
|
|
|
154
237
|
Args:
|
|
155
238
|
param: Hybrid wirebon parameters.
|
|
156
239
|
|
|
157
240
|
"""
|
|
241
|
+
self.win = win
|
|
158
242
|
self.id = hid
|
|
159
243
|
self.param = param
|
|
160
244
|
self.nchan = 0
|
|
@@ -163,116 +247,120 @@ class HybridHoles:
|
|
|
163
247
|
|
|
164
248
|
self.holes = [[] for irow in range(4)]
|
|
165
249
|
self.channels = [[] for irow in range(4)]
|
|
250
|
+
# Sensor strips for each of the strip rows "served" by a hybrid.
|
|
251
|
+
self.sensor_channels = [[], []]
|
|
252
|
+
self.sensor_holes = [[], []]
|
|
253
|
+
|
|
254
|
+
def ready(self):
|
|
255
|
+
"""Call when all channels are in."""
|
|
256
|
+
for irow, C in enumerate(self.channels):
|
|
257
|
+
C.sort()
|
|
258
|
+
self.holes[irow] = find_holes(C)
|
|
259
|
+
|
|
260
|
+
for irow, S in enumerate(self.sensor_channels):
|
|
261
|
+
S.sort()
|
|
262
|
+
self.sensor_holes[irow] = find_holes(S)
|
|
166
263
|
|
|
167
264
|
def add_channel(self, irow, ichan)->bool:
|
|
168
265
|
"""Add a new channel in row.
|
|
169
266
|
|
|
170
267
|
Args:
|
|
171
|
-
irow:
|
|
268
|
+
irow: row number
|
|
172
269
|
ichan: channel number
|
|
173
270
|
|
|
174
271
|
Returns:
|
|
175
272
|
True if added, False otherwise.
|
|
176
|
-
|
|
273
|
+
|
|
177
274
|
"""
|
|
178
275
|
first_chan = self.param[irow][0]
|
|
179
276
|
last_chan = self.param[irow][1]
|
|
277
|
+
strip_row = int(irow/2)
|
|
278
|
+
|
|
279
|
+
|
|
180
280
|
if isinstance(ichan, list) or isinstance(ichan, tuple):
|
|
181
281
|
nadded = 0
|
|
182
282
|
for ich in ichan:
|
|
183
|
-
if
|
|
283
|
+
if first_chan <= ich <= last_chan:
|
|
184
284
|
self.channels[irow].append(ich)
|
|
185
285
|
nadded += 1
|
|
186
286
|
|
|
187
287
|
self.channels[irow] = sorted(self.channels[irow])
|
|
288
|
+
for iwire in self.channels[irow]:
|
|
289
|
+
istrip = wire2strip(iwire, irow, first_chan)
|
|
290
|
+
self.sensor_channels[strip_row].append(istrip)
|
|
291
|
+
|
|
188
292
|
return nadded>0
|
|
189
|
-
else:
|
|
190
|
-
if ichan >= first_chan and ichan <= last_chan:
|
|
191
|
-
self.channels[irow].append(ichan)
|
|
192
|
-
return True
|
|
193
|
-
else:
|
|
194
|
-
return False
|
|
195
293
|
|
|
196
|
-
|
|
294
|
+
if first_chan <= ichan <= last_chan:
|
|
295
|
+
self.channels[irow].append(ichan)
|
|
296
|
+
istrip = wire2strip(ichan, irow, first_chan)
|
|
297
|
+
self.sensor_channels[strip_row].append(istrip)
|
|
298
|
+
return True
|
|
299
|
+
|
|
300
|
+
return False
|
|
301
|
+
|
|
302
|
+
def get_n_unconnected(self) -> list:
|
|
197
303
|
"""Count number of unconnected channels.
|
|
198
304
|
|
|
199
305
|
Return a list, one item per row.
|
|
200
306
|
"""
|
|
201
|
-
nchan = []
|
|
202
|
-
for row in self.holes:
|
|
203
|
-
nch = 0
|
|
204
|
-
for h in row:
|
|
205
|
-
nch += h[1]
|
|
206
|
-
|
|
207
|
-
nchan.append(nch)
|
|
208
|
-
|
|
307
|
+
nchan = [len(C) for C in self.channels]
|
|
209
308
|
return nchan
|
|
210
309
|
|
|
211
|
-
def
|
|
212
|
-
"""
|
|
310
|
+
def get_max_consecutive_from_list(self, holes):
|
|
311
|
+
"""Return max widht of holes."""
|
|
213
312
|
mx_width = []
|
|
313
|
+
lst_holes = []
|
|
314
|
+
for irow, row in enumerate(holes):
|
|
315
|
+
if len(row) == 0:
|
|
316
|
+
mxW = 0
|
|
214
317
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
mxW = h[1]
|
|
318
|
+
else:
|
|
319
|
+
mxW = -1
|
|
320
|
+
for h in row:
|
|
321
|
+
lst_holes.append(Hole(0, self.id, irow, h[0], h[1]))
|
|
322
|
+
mxW = max(mxW, h[1])
|
|
220
323
|
|
|
221
324
|
mx_width.append(mxW)
|
|
222
325
|
|
|
223
|
-
return mx_width
|
|
224
|
-
|
|
225
|
-
def get_sensor_holes(self):
|
|
226
|
-
"""Compute holes in 'sensor' strips.
|
|
227
|
-
|
|
228
|
-
Each hybrid has 2 sensor segments corresponding to
|
|
229
|
-
rows (1,2) and (3, 4).
|
|
230
|
-
|
|
231
|
-
Return a list of [sensor, hybrid, segment, ichan, width]
|
|
232
|
-
"""
|
|
233
|
-
holes = []
|
|
234
|
-
channels = [[], []]
|
|
235
|
-
for irow, row in enumerate(self.channels):
|
|
236
|
-
isegment = int(irow/2)
|
|
237
|
-
for ich in row:
|
|
238
|
-
rng = self.param[irow]
|
|
239
|
-
if irow % 2:
|
|
240
|
-
chan = 2*(ich-rng[0]) + 1
|
|
241
|
-
else:
|
|
242
|
-
chan = 2*(ich-rng[0])
|
|
243
|
-
|
|
244
|
-
channels[isegment].append(chan)
|
|
245
|
-
|
|
246
|
-
channels[isegment] = sorted(channels[isegment])
|
|
326
|
+
return mx_width, lst_holes
|
|
247
327
|
|
|
248
|
-
for isegment, S in enumerate(channels):
|
|
249
|
-
H = find_holes(S)
|
|
250
|
-
if len(H)>0:
|
|
251
|
-
out = [ [0, self.id, isegment, chan, width] for chan, width in H ]
|
|
252
|
-
holes.extend(out)
|
|
253
328
|
|
|
254
|
-
|
|
329
|
+
def get_max_consecutive(self):
|
|
330
|
+
"""Returns the largest 'hole'."""
|
|
331
|
+
mx_width, _ = self.get_max_consecutive_from_list(self.holes)
|
|
332
|
+
return mx_width
|
|
255
333
|
|
|
334
|
+
def get_max_sensor_consecutive(self):
|
|
335
|
+
"""Return largest hole in sensor."""
|
|
336
|
+
mx_width, holes = self.get_max_consecutive_from_list(self.sensor_holes)
|
|
337
|
+
return mx_width, holes
|
|
256
338
|
|
|
257
339
|
class SensorHoles:
|
|
258
340
|
"""Holes in sensor."""
|
|
259
341
|
|
|
260
|
-
def __init__(self, param, sid=0):
|
|
342
|
+
def __init__(self, param, win=None, sid=0):
|
|
261
343
|
"""Initialization.
|
|
262
344
|
|
|
263
345
|
Args:
|
|
264
346
|
param: sensor wirebon params
|
|
265
347
|
"""
|
|
348
|
+
self.win = win
|
|
266
349
|
self.id = sid
|
|
267
350
|
self.param = param
|
|
268
351
|
self.nchan = 0
|
|
269
352
|
self.nhybrid = len(param)
|
|
270
353
|
self.hybrids = []
|
|
271
354
|
for i, P in enumerate(param):
|
|
272
|
-
H = HybridHoles(P, hid=i)
|
|
355
|
+
H = HybridHoles(P, hid=i, win=win)
|
|
273
356
|
self.hybrids.append(H)
|
|
274
357
|
self.nchan += H.nchan
|
|
275
358
|
|
|
359
|
+
def ready(self):
|
|
360
|
+
"""Call when all channels are in."""
|
|
361
|
+
for H in self.hybrids:
|
|
362
|
+
H.ready()
|
|
363
|
+
|
|
276
364
|
def get_n_hyb(self):
|
|
277
365
|
"""Return number of hybrids."""
|
|
278
366
|
return len(self.hybrids)
|
|
@@ -286,15 +374,29 @@ class SensorHoles:
|
|
|
286
374
|
|
|
287
375
|
This is ordered by row.
|
|
288
376
|
"""
|
|
289
|
-
mx_width = [0
|
|
377
|
+
mx_width = [0 for x in range(4)]
|
|
290
378
|
for hyb in self.hybrids:
|
|
291
379
|
mxW = hyb.get_max_consecutive()
|
|
292
|
-
for j in
|
|
293
|
-
|
|
294
|
-
mx_width[j] = mxW[j]
|
|
380
|
+
for j, val in enumerate(mxW):
|
|
381
|
+
mx_width[j] = max(mx_width[j] , val)
|
|
295
382
|
|
|
296
383
|
return mx_width
|
|
297
384
|
|
|
385
|
+
def get_max_sensor_consecutive(self):
|
|
386
|
+
"""MAx widht of holes in sensor."""
|
|
387
|
+
mx_width = -1
|
|
388
|
+
holes = []
|
|
389
|
+
for hyb in self.hybrids:
|
|
390
|
+
mxW, hyb_holes = hyb.get_max_sensor_consecutive()
|
|
391
|
+
for H in hyb_holes:
|
|
392
|
+
H.sensor = self.id
|
|
393
|
+
|
|
394
|
+
holes.extend(hyb_holes)
|
|
395
|
+
for v in mxW:
|
|
396
|
+
mx_width = max(mx_width, v)
|
|
397
|
+
|
|
398
|
+
return mx_width, holes
|
|
399
|
+
|
|
298
400
|
def get_n_unconnected(self):
|
|
299
401
|
"""Count number of unconnected channels.
|
|
300
402
|
|
|
@@ -308,37 +410,30 @@ class SensorHoles:
|
|
|
308
410
|
|
|
309
411
|
return nchan
|
|
310
412
|
|
|
311
|
-
def get_sensor_holes(self):
|
|
312
|
-
"""Return holes sensor.
|
|
313
|
-
|
|
314
|
-
Return a list of [sensor, hybrid, segment, ichan, width]
|
|
315
|
-
"""
|
|
316
|
-
holes = []
|
|
317
|
-
for hyb in self.hybrids:
|
|
318
|
-
H = hyb.get_sensor_holes()
|
|
319
|
-
for _, ih, isegment, ichan, width in H:
|
|
320
|
-
holes.append([self.id, ih, isegment, ichan, width])
|
|
321
|
-
|
|
322
|
-
return holes
|
|
323
|
-
|
|
324
413
|
|
|
325
414
|
class ModuleHoles:
|
|
326
415
|
"""Holes in Modules."""
|
|
327
416
|
|
|
328
|
-
def __init__(self, param):
|
|
417
|
+
def __init__(self, param, win=None):
|
|
329
418
|
"""Initialization.
|
|
330
419
|
|
|
331
420
|
Args:
|
|
332
421
|
param: module wirebond params
|
|
333
422
|
"""
|
|
423
|
+
self.win = win
|
|
334
424
|
self.nsensor = len(param)
|
|
335
425
|
self.nchan = 0
|
|
336
426
|
self.sensors = []
|
|
337
427
|
for i, P in enumerate(param):
|
|
338
|
-
S = SensorHoles(P, sid=i)
|
|
428
|
+
S = SensorHoles(P, sid=i, win=win)
|
|
339
429
|
self.sensors.append(S)
|
|
340
430
|
self.nchan += S.nchan
|
|
341
431
|
|
|
432
|
+
def ready(self):
|
|
433
|
+
"""Call when all channels are in."""
|
|
434
|
+
for S in self.sensors:
|
|
435
|
+
S.ready()
|
|
436
|
+
|
|
342
437
|
def get_max_consecutive(self):
|
|
343
438
|
"""Max number of consecutive unconnected channels.
|
|
344
439
|
|
|
@@ -348,22 +443,21 @@ class ModuleHoles:
|
|
|
348
443
|
for S in self.sensors:
|
|
349
444
|
mxW = S.get_max_consecutive()
|
|
350
445
|
for j in range(4):
|
|
351
|
-
|
|
352
|
-
mx_width[j] = mxW[j]
|
|
446
|
+
mx_width[j] = max(mx_width[j], mxW[j])
|
|
353
447
|
|
|
354
448
|
return mx_width
|
|
355
449
|
|
|
356
|
-
def
|
|
357
|
-
"""
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
"""
|
|
361
|
-
holes = []
|
|
450
|
+
def get_max_sensor_consecutive(self):
|
|
451
|
+
"""The maximum number of consecutive channels per strip row."""
|
|
452
|
+
mx_width = -1
|
|
453
|
+
module_holes = []
|
|
362
454
|
for S in self.sensors:
|
|
363
|
-
|
|
364
|
-
|
|
455
|
+
width, holes = S.get_max_sensor_consecutive()
|
|
456
|
+
module_holes.extend(holes)
|
|
457
|
+
mx_width = max(mx_width, width)
|
|
458
|
+
|
|
459
|
+
return mx_width, module_holes
|
|
365
460
|
|
|
366
|
-
return holes
|
|
367
461
|
|
|
368
462
|
def get_n_unconnected(self) -> list:
|
|
369
463
|
"""Count number of unconnected channels.
|
|
@@ -416,16 +510,20 @@ def get_module_param(SN):
|
|
|
416
510
|
class WireBond(dbGtkUtils.ITkDBWindow):
|
|
417
511
|
"""Main window."""
|
|
418
512
|
|
|
419
|
-
def __init__(self, session, title="",
|
|
513
|
+
def __init__(self, session, title="", help_link=__HELP_LINK__):
|
|
420
514
|
"""Initialization."""
|
|
421
|
-
super().__init__(title=title, session=session,
|
|
515
|
+
super().__init__(title=title, session=session, help_link=help_link)
|
|
422
516
|
self.pdb = None
|
|
423
517
|
self.models = {}
|
|
424
518
|
self.holes = {}
|
|
425
|
-
self.institute = "
|
|
519
|
+
self.institute = self.pdb_user["institutions"][0]["code"]
|
|
426
520
|
self.inst_combo = None
|
|
427
521
|
self.module_SN = None
|
|
428
522
|
self.alternativeID = None
|
|
523
|
+
self.combo = None
|
|
524
|
+
self.tree = None
|
|
525
|
+
self.lut = {}
|
|
526
|
+
self.module_type = None
|
|
429
527
|
self.init_window()
|
|
430
528
|
|
|
431
529
|
def init_window(self):
|
|
@@ -460,17 +558,33 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
460
558
|
|
|
461
559
|
# Data panel
|
|
462
560
|
grid = Gtk.Grid(column_spacing=5, row_spacing=1)
|
|
463
|
-
|
|
561
|
+
|
|
464
562
|
# The shipment receiver
|
|
465
|
-
institute = self.create_institute_combo()
|
|
563
|
+
institute = self.create_institute_combo(True)
|
|
466
564
|
institute.connect("changed", self.on_institute)
|
|
467
565
|
institute.set_tooltip_text("Select the Institute.")
|
|
468
566
|
dbGtkUtils.set_combo_iter(institute, self.institute)
|
|
469
|
-
|
|
567
|
+
|
|
568
|
+
lbl = Gtk.Label(label="Institute")
|
|
569
|
+
lbl.set_xalign(0)
|
|
570
|
+
grid.attach(lbl, 0, 0, 1, 1)
|
|
470
571
|
grid.attach(institute, 1, 0, 1, 1)
|
|
471
572
|
self.inst_combo = institute
|
|
472
|
-
|
|
473
|
-
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
# The lookup table
|
|
577
|
+
lbl = Gtk.Label(label="Lookup Table")
|
|
578
|
+
lbl.set_xalign(0)
|
|
579
|
+
grid.attach(lbl, 2, 0, 1, 1)
|
|
580
|
+
|
|
581
|
+
self.testF = Gtk.FileChooserButton()
|
|
582
|
+
self.testF.set_tooltip_text("Click to select Lookup table.")
|
|
583
|
+
|
|
584
|
+
grid.attach(self.testF, 3, 0, 1, 1)
|
|
585
|
+
self.testF.connect("file-set", self.on_lut)
|
|
586
|
+
|
|
587
|
+
|
|
474
588
|
for i, tit in enumerate(["Operator", "Bond Machine", "Wire Batch", "SN", "Date"]):
|
|
475
589
|
lbl = Gtk.Label(label=tit)
|
|
476
590
|
lbl.set_xalign(0)
|
|
@@ -480,11 +594,11 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
480
594
|
self.machine = dbGtkUtils.new_small_text_entry()
|
|
481
595
|
self.batch = dbGtkUtils.new_small_text_entry()
|
|
482
596
|
#self.SN = dbGtkUtils.new_small_text_entry()
|
|
483
|
-
|
|
597
|
+
|
|
484
598
|
self.SN = itkdb_gtk.dbGtkUtils.TextEntry(small=True)
|
|
485
599
|
self.SN.connect("text-changed", self.on_SN_changed)
|
|
486
600
|
|
|
487
|
-
|
|
601
|
+
|
|
488
602
|
self.date = dbGtkUtils.TextEntry(small=True)
|
|
489
603
|
self.date.entry.set_text(ITkDButils.get_db_date())
|
|
490
604
|
self.date.connect("text_changed", self.new_date)
|
|
@@ -511,32 +625,135 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
511
625
|
|
|
512
626
|
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
|
|
513
627
|
self.mainBox.pack_start(box, False, False, 0)
|
|
514
|
-
dbGtkUtils.add_button_to_container(box, "Add
|
|
515
|
-
"Click to add a new
|
|
628
|
+
dbGtkUtils.add_button_to_container(box, "Add Bond",
|
|
629
|
+
"Click to add a new bond or bond range.",
|
|
516
630
|
self.add_item)
|
|
517
631
|
|
|
632
|
+
dbGtkUtils.add_button_to_container(box, "Remove Bond",
|
|
633
|
+
"Click to remove selected bond.",
|
|
634
|
+
self.remove_item)
|
|
635
|
+
|
|
518
636
|
#
|
|
519
637
|
# The text view and buffer
|
|
520
638
|
#
|
|
521
639
|
self.mainBox.pack_start(self.message_panel.frame, True, True, 0)
|
|
522
640
|
self.write_message("wirebond GUI\n")
|
|
523
641
|
|
|
642
|
+
def on_lut(self, fdlg):
|
|
643
|
+
"""Get look-up table."""
|
|
644
|
+
fnam = Path(fdlg.get_filename())
|
|
645
|
+
if not fnam.exists():
|
|
646
|
+
dbGtkUtils.complain("Cannot open Luukup Table.",
|
|
647
|
+
"File {} does not exist.".format(fnam))
|
|
648
|
+
return
|
|
649
|
+
|
|
650
|
+
lut = {}
|
|
651
|
+
module_map = {}
|
|
652
|
+
section = None
|
|
653
|
+
i_local = 0
|
|
654
|
+
i_std = 1
|
|
655
|
+
indx = ["local", "standard"]
|
|
656
|
+
found_format = False
|
|
657
|
+
with open(fnam, 'r', encoding="UTF-8") as fin:
|
|
658
|
+
for line in fin:
|
|
659
|
+
line = line.strip()
|
|
660
|
+
|
|
661
|
+
# Remove comments.
|
|
662
|
+
ipos = line.find('#')
|
|
663
|
+
jpos = line.find("#!")
|
|
664
|
+
if jpos>=0 and ipos==jpos:
|
|
665
|
+
if found_format:
|
|
666
|
+
dbGtkUtils.complain("A second format line was found.",
|
|
667
|
+
"Onely one is allowed. stopr map parsing.")
|
|
668
|
+
return
|
|
669
|
+
|
|
670
|
+
indx = [x.lower() for x in line[ipos+2:].split()]
|
|
671
|
+
try:
|
|
672
|
+
i_local = indx.index("local")
|
|
673
|
+
i_std = indx.index("standard")
|
|
674
|
+
found_format = True
|
|
675
|
+
except ValueError:
|
|
676
|
+
dbGtkUtils.complain("Wrong format desciption string.",
|
|
677
|
+
"The words 'local' and 'standard' should be there.\n{}".format(line))
|
|
678
|
+
return
|
|
679
|
+
|
|
680
|
+
continue
|
|
681
|
+
|
|
682
|
+
if ipos >= 0:
|
|
683
|
+
line = line[:ipos].strip()
|
|
684
|
+
|
|
685
|
+
if len(line) == 0:
|
|
686
|
+
continue
|
|
687
|
+
|
|
688
|
+
# Check for new section
|
|
689
|
+
ipos = line.find(':')
|
|
690
|
+
if ipos >= 0:
|
|
691
|
+
section = line[:ipos].strip().upper()
|
|
692
|
+
if section in module_map:
|
|
693
|
+
dbGtkUtils.complain("Section {} already in map.".format(section), "Stop parsing bond Lookup table.")
|
|
694
|
+
return
|
|
695
|
+
|
|
696
|
+
lut = {}
|
|
697
|
+
module_map[section] = lut
|
|
698
|
+
continue
|
|
699
|
+
|
|
700
|
+
if section is None:
|
|
701
|
+
continue
|
|
702
|
+
|
|
703
|
+
values = line.split()
|
|
704
|
+
if len(values)!=len(indx):
|
|
705
|
+
dbGtkUtils.complain("Cannot read Lookup table.", "Wrong line format: {}".format(line))
|
|
706
|
+
return
|
|
707
|
+
|
|
708
|
+
v_local = range_to_list(values[i_local])
|
|
709
|
+
v_std = range_to_list(values[i_std])
|
|
710
|
+
|
|
711
|
+
if len(v_local) != len(v_std):
|
|
712
|
+
dbGtkUtils.complain("Wrong Lookup table.",
|
|
713
|
+
"Ranges have different length: {}".format(line))
|
|
714
|
+
return
|
|
715
|
+
|
|
716
|
+
for L, S in zip(v_local, v_std):
|
|
717
|
+
lut[L] = S
|
|
718
|
+
|
|
719
|
+
self.lut = module_map
|
|
720
|
+
|
|
721
|
+
def convert_channel(self, C):
|
|
722
|
+
"""Convert channel according to LUT
|
|
723
|
+
|
|
724
|
+
Args:
|
|
725
|
+
C (str): channel number
|
|
726
|
+
|
|
727
|
+
"""
|
|
728
|
+
try:
|
|
729
|
+
return self.lut[self.module_type][C]
|
|
730
|
+
|
|
731
|
+
except KeyError:
|
|
732
|
+
return C
|
|
733
|
+
|
|
524
734
|
def on_institute(self, combo):
|
|
525
735
|
"""Institute changed."""
|
|
526
736
|
name = self.get_institute_from_combo(combo)
|
|
527
737
|
if name:
|
|
528
738
|
self.institute = name
|
|
529
|
-
|
|
739
|
+
|
|
530
740
|
def on_SN_changed(self, entry, value):
|
|
531
741
|
"""New SN given. Ask in PDB,"""
|
|
532
742
|
if len(value) <= 0:
|
|
533
|
-
return
|
|
534
|
-
|
|
743
|
+
return
|
|
535
744
|
|
|
536
745
|
obj = itkdb_gtk.ITkDButils.get_DB_component(self.session, value)
|
|
537
|
-
if obj is not None:
|
|
746
|
+
if obj is not None and obj["serialNumber"] is not None:
|
|
538
747
|
entry.set_text(obj["serialNumber"])
|
|
539
|
-
|
|
748
|
+
alternativeID = obj["alternativeIdentifier"]
|
|
749
|
+
module_SN = obj["serialNumber"]
|
|
750
|
+
if len(module_SN) == 14 and module_SN.startswith("20USEM"):
|
|
751
|
+
self.module_SN = module_SN
|
|
752
|
+
self.alternativeID = alternativeID
|
|
753
|
+
self.module_type = module_SN[5:7]
|
|
754
|
+
|
|
755
|
+
else:
|
|
756
|
+
itkdb_gtk.dbGtkUtils.complain("Invalid SN: {}".format(module_SN), "Not a Ring module")
|
|
540
757
|
|
|
541
758
|
else:
|
|
542
759
|
itkdb_gtk.dbGtkUtils.complain("Invalid SN", value)
|
|
@@ -550,7 +767,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
550
767
|
view_model = self.models[param]
|
|
551
768
|
self.tree.set_model(view_model)
|
|
552
769
|
else:
|
|
553
|
-
self.write_message("Cannot find model for {}".format(param))
|
|
770
|
+
self.write_message("Cannot find model for {}\n".format(param))
|
|
554
771
|
|
|
555
772
|
def create_combo(self):
|
|
556
773
|
"""Create the combo."""
|
|
@@ -614,8 +831,9 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
614
831
|
def channel_edited(self, widget, path, text):
|
|
615
832
|
"""Handles edition in channel number cell."""
|
|
616
833
|
if not text.isnumeric():
|
|
617
|
-
|
|
618
|
-
|
|
834
|
+
if valid_channel.match(text) is None:
|
|
835
|
+
dbGtkUtils.complain("Wrong channel number", "Invalid channel number: {}".format(text))
|
|
836
|
+
return
|
|
619
837
|
|
|
620
838
|
self.text_edited(0, path, text)
|
|
621
839
|
|
|
@@ -630,9 +848,52 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
630
848
|
if d is not None:
|
|
631
849
|
self.date.set_text(d)
|
|
632
850
|
|
|
633
|
-
def button_pressed(self,
|
|
851
|
+
def button_pressed(self, tree, event):
|
|
634
852
|
"""Button pressed."""
|
|
635
|
-
|
|
853
|
+
# double click shows attachments
|
|
854
|
+
if event.button == 1 and event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
|
|
855
|
+
#self.write_message("This is a double click.\n")
|
|
856
|
+
return
|
|
857
|
+
|
|
858
|
+
if event.button != 3:
|
|
859
|
+
return
|
|
860
|
+
|
|
861
|
+
# Create popup menu
|
|
862
|
+
select = self.tree.get_selection()
|
|
863
|
+
model, lv_iter = select.get_selected()
|
|
864
|
+
values = None
|
|
865
|
+
if lv_iter:
|
|
866
|
+
values = model[lv_iter]
|
|
867
|
+
|
|
868
|
+
else:
|
|
869
|
+
P = tree.get_path_at_pos(event.x, event.y)
|
|
870
|
+
if P:
|
|
871
|
+
lv_iter = model.get_iter(P[0])
|
|
872
|
+
values = model[lv_iter]
|
|
873
|
+
|
|
874
|
+
if not values:
|
|
875
|
+
return
|
|
876
|
+
|
|
877
|
+
menu = Gtk.Menu()
|
|
878
|
+
|
|
879
|
+
item_show = Gtk.MenuItem(label="Delete")
|
|
880
|
+
item_show.connect("activate", self.on_delete_item, (model, lv_iter, values))
|
|
881
|
+
menu.append(item_show)
|
|
882
|
+
|
|
883
|
+
menu.show_all()
|
|
884
|
+
menu.popup_at_pointer(event)
|
|
885
|
+
|
|
886
|
+
def on_delete_item(self, item, data):
|
|
887
|
+
"""Delete bond in list view."""
|
|
888
|
+
model, lv_iter, _ = data
|
|
889
|
+
model.remove(lv_iter)
|
|
890
|
+
|
|
891
|
+
def remove_item(self, *args):
|
|
892
|
+
"""REmoves selected bond."""
|
|
893
|
+
select = self.tree.get_selection()
|
|
894
|
+
model, lv_iter = select.get_selected()
|
|
895
|
+
if lv_iter:
|
|
896
|
+
model.remove(lv_iter)
|
|
636
897
|
|
|
637
898
|
def add_item(self, *args):
|
|
638
899
|
"""Adds a new item in the current model."""
|
|
@@ -650,16 +911,72 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
650
911
|
self.hide()
|
|
651
912
|
self.destroy()
|
|
652
913
|
|
|
653
|
-
def
|
|
914
|
+
def compute_repaired(self, skeleton):
|
|
915
|
+
"""Compute number of repaired."""
|
|
916
|
+
nrepaired = 0
|
|
917
|
+
for key, values in skeleton["results"].items():
|
|
918
|
+
if key.find("REPAIRED")<0 or key.find("ROW")<0:
|
|
919
|
+
continue
|
|
920
|
+
|
|
921
|
+
nrepaired += len(values)
|
|
922
|
+
|
|
923
|
+
if nrepaired>0:
|
|
924
|
+
skeleton["problems"] = True
|
|
925
|
+
skeleton["comments"].append("Number of repaired FE bonds: {}".format(nrepaired))
|
|
926
|
+
|
|
927
|
+
return nrepaired
|
|
928
|
+
|
|
929
|
+
def compute_hybrid_to_pb(self, skeleton):
|
|
930
|
+
"""Compute number of failures and repairs."""
|
|
931
|
+
n = count_items(skeleton["results"]["REPAIRED_HYBRID_TO_PB"])
|
|
932
|
+
n = count_items(skeleton["results"]["FAILED_HYBRID_TO_PB"])
|
|
933
|
+
if n:
|
|
934
|
+
msg = "Hybrid to PB: {} failing bonds.".format(n)
|
|
935
|
+
skeleton["comments"].append(msg)
|
|
936
|
+
skeleton["passed"] = False
|
|
937
|
+
self.write_message("{}\n".format(msg))
|
|
938
|
+
for key in skeleton["results"]["FAILED_HYBRID_TO_PB"]:
|
|
939
|
+
defect = {
|
|
940
|
+
"description": "Unbonded: Hybrid to PB",
|
|
941
|
+
"name": "UNBODED",
|
|
942
|
+
"properties": {
|
|
943
|
+
"wire_number": range_to_list(key)
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
skeleton["defects"].append(defect)
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
def compute_module_to_frame(self, skeleton):
|
|
950
|
+
"""Compute number of failures and repairs."""
|
|
951
|
+
n = count_items(skeleton["results"]["REPAIRED_MODULE_TO_FRAME"])
|
|
952
|
+
n = count_items(skeleton["results"]["FAILED_MODULE_TO_FRAME"])
|
|
953
|
+
if n:
|
|
954
|
+
msg = "Module to test frame: {} failing bonds.".format(n)
|
|
955
|
+
skeleton["comments"].append(msg)
|
|
956
|
+
skeleton["passed"] = False
|
|
957
|
+
self.write_message("{}\n".format(msg))
|
|
958
|
+
for key in skeleton["results"]["FAILED_MODULE_TO_FRAME"]:
|
|
959
|
+
defect = {
|
|
960
|
+
"description": "Unbonded: Module to Frame",
|
|
961
|
+
"name": "UNBODED",
|
|
962
|
+
"properties": {
|
|
963
|
+
"wire_number": range_to_list(key)
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
skeleton["defects"].append(defect)
|
|
967
|
+
|
|
968
|
+
def compute_unconnected(self, results):
|
|
654
969
|
"""Compute number of unconnected."""
|
|
655
970
|
try:
|
|
656
971
|
param = get_module_param(self.SN.get_text())
|
|
657
972
|
except ValueError as E:
|
|
658
973
|
dbGtkUtils.complain("Wrong SN number", str(E))
|
|
659
|
-
|
|
660
|
-
M = ModuleHoles(param=param)
|
|
974
|
+
return None
|
|
661
975
|
|
|
662
|
-
|
|
976
|
+
M = ModuleHoles(param=param, win=self)
|
|
977
|
+
|
|
978
|
+
defects = []
|
|
979
|
+
for test, values in results.items():
|
|
663
980
|
if test.find("FAILED") < 0:
|
|
664
981
|
continue
|
|
665
982
|
if test.find("ROW") < 0:
|
|
@@ -668,56 +985,86 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
668
985
|
irow = int(test[-1]) - 1
|
|
669
986
|
|
|
670
987
|
# Get list of all channels with wirebond notation.
|
|
671
|
-
|
|
672
|
-
it = model.get_iter_first()
|
|
673
|
-
out = []
|
|
674
|
-
while it:
|
|
675
|
-
chan, _ = model[it]
|
|
676
|
-
if len(chan) > 0:
|
|
677
|
-
out.append(int(chan))
|
|
678
|
-
|
|
679
|
-
it = model.iter_next(it)
|
|
680
|
-
|
|
988
|
+
out = [int(x) for x in values.keys()]
|
|
681
989
|
# Translate to sensor, hybrids, etc.
|
|
682
990
|
for S in M.sensors:
|
|
683
991
|
for H in S.hybrids:
|
|
684
992
|
H.add_channel(irow, out)
|
|
685
993
|
H.holes[irow] = find_holes(H.channels[irow])
|
|
686
994
|
|
|
995
|
+
# add defects
|
|
996
|
+
defects.append(
|
|
997
|
+
{
|
|
998
|
+
"description": "Unbonded Channel",
|
|
999
|
+
"name": "UNBONDED",
|
|
1000
|
+
"properties": {
|
|
1001
|
+
"front_end_row": irow,
|
|
1002
|
+
"wire_number": out
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
)
|
|
687
1006
|
|
|
688
1007
|
# Now get sensor strips.
|
|
1008
|
+
M.ready()
|
|
689
1009
|
unconnected = M.get_n_unconnected()
|
|
690
1010
|
mx_consecutive = M.get_max_consecutive()
|
|
691
|
-
module_holes = M.
|
|
1011
|
+
mx_sensor_width, module_holes = M.get_max_sensor_consecutive()
|
|
692
1012
|
|
|
693
1013
|
out = {}
|
|
1014
|
+
out["comments"] = []
|
|
1015
|
+
out["defects"] = defects
|
|
694
1016
|
for irow in range(4):
|
|
695
1017
|
key = "MAX_CONT_UNCON_ROW{}".format(irow+1)
|
|
696
1018
|
out[key] = mx_consecutive[irow]
|
|
697
1019
|
|
|
698
|
-
mxW = 0
|
|
699
1020
|
self.write_message("Found {} clusters of unconnected strips in sensor.\n".format(len(module_holes)))
|
|
700
1021
|
for H in module_holes:
|
|
701
|
-
self.write_message("{}\n".format(
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1022
|
+
self.write_message("{}\n".format(H))
|
|
1023
|
+
|
|
1024
|
+
if mx_sensor_width > 0:
|
|
1025
|
+
self.write_message("Max width of consecutive unconnected strips: {}\n". format(mx_sensor_width))
|
|
1026
|
+
|
|
1027
|
+
out["MAX_UNCON_SENSOR_CHAN"] = mx_sensor_width
|
|
1028
|
+
if mx_sensor_width > 8:
|
|
1029
|
+
out["passed"] = False
|
|
1030
|
+
out["comments"].append("Too many consecutive sensor strips unconnected: {}".format(mx_sensor_width))
|
|
1031
|
+
|
|
709
1032
|
nstrips = 0
|
|
710
1033
|
for v in unconnected:
|
|
711
1034
|
nstrips += v
|
|
712
1035
|
|
|
713
|
-
|
|
1036
|
+
percent = 100*nstrips/M.nchan
|
|
1037
|
+
out["TOTAL_PERC_UNCON_SENSOR_CHAN"] = percent
|
|
1038
|
+
if out["TOTAL_PERC_UNCON_SENSOR_CHAN"] > 1.0:
|
|
1039
|
+
out["passed"] = False
|
|
1040
|
+
out["comments"].append("More than 1%% of channels unconnected: {:.1f}%%".format(percent))
|
|
714
1041
|
|
|
715
1042
|
return out
|
|
716
1043
|
|
|
717
1044
|
def get_unconnected(self, skeleton):
|
|
718
1045
|
"""Fill the test DTO with unconnected information."""
|
|
719
|
-
out = self.compute_unconnected()
|
|
1046
|
+
out = self.compute_unconnected(skeleton["results"])
|
|
1047
|
+
if out is None:
|
|
1048
|
+
raise ValueError("Wrong SN")
|
|
1049
|
+
|
|
720
1050
|
for key, val in out.items():
|
|
1051
|
+
if key in ["passed", "problems"]:
|
|
1052
|
+
skeleton[key] = out[key]
|
|
1053
|
+
continue
|
|
1054
|
+
|
|
1055
|
+
if key == "comments":
|
|
1056
|
+
for C in out[key]:
|
|
1057
|
+
skeleton[key].append(C)
|
|
1058
|
+
|
|
1059
|
+
continue
|
|
1060
|
+
|
|
1061
|
+
if key == "defects":
|
|
1062
|
+
for D in out[key]:
|
|
1063
|
+
skeleton[key].append(D)
|
|
1064
|
+
|
|
1065
|
+
continue
|
|
1066
|
+
|
|
1067
|
+
|
|
721
1068
|
skeleton["results"][key] = val
|
|
722
1069
|
|
|
723
1070
|
def read_file(self, *args):
|
|
@@ -754,8 +1101,8 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
754
1101
|
try:
|
|
755
1102
|
dbGtkUtils.set_combo_iter(self.inst_combo, data["institution"])
|
|
756
1103
|
except KeyError:
|
|
757
|
-
self.write_message("institution value is not in the loaded file.")
|
|
758
|
-
|
|
1104
|
+
self.write_message("institution value is not in the loaded file\n.")
|
|
1105
|
+
|
|
759
1106
|
self.operator.set_text(data["properties"]["OPERATOR"])
|
|
760
1107
|
self.machine.set_text(data["properties"]["BOND_MACHINE"])
|
|
761
1108
|
self.batch.set_text(data["properties"]["BONDWIRE_BATCH"])
|
|
@@ -772,17 +1119,54 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
772
1119
|
def get_list_of_channels(self, data):
|
|
773
1120
|
"""Creates the lists of channels."""
|
|
774
1121
|
for key, model in self.models.items():
|
|
775
|
-
|
|
1122
|
+
lv_iter = model.get_iter_first()
|
|
776
1123
|
out = {}
|
|
777
|
-
while
|
|
778
|
-
chan, comm = model[
|
|
1124
|
+
while lv_iter:
|
|
1125
|
+
chan, comm = model[lv_iter]
|
|
779
1126
|
if len(chan) > 0:
|
|
780
1127
|
out[chan] = comm
|
|
781
1128
|
|
|
782
|
-
|
|
1129
|
+
lv_iter = model.iter_next(lv_iter)
|
|
783
1130
|
|
|
784
1131
|
data["results"][key] = out
|
|
785
1132
|
|
|
1133
|
+
def fix_list_of_channels(self, data):
|
|
1134
|
+
"""Expand ranges and, eventually, apply LUT.
|
|
1135
|
+
|
|
1136
|
+
Args:
|
|
1137
|
+
data: The test payload.
|
|
1138
|
+
"""
|
|
1139
|
+
for tit, section in data["results"].items():
|
|
1140
|
+
if not isinstance(section, dict):
|
|
1141
|
+
continue
|
|
1142
|
+
|
|
1143
|
+
range_items = []
|
|
1144
|
+
added_items = []
|
|
1145
|
+
for key, comment in section.items():
|
|
1146
|
+
values = list(map(str.strip, key.split(',')))
|
|
1147
|
+
if ',' in key or '-' in key:
|
|
1148
|
+
range_items.append(key)
|
|
1149
|
+
|
|
1150
|
+
else:
|
|
1151
|
+
continue
|
|
1152
|
+
|
|
1153
|
+
for V in values:
|
|
1154
|
+
for i in range_to_list(V):
|
|
1155
|
+
added_items.append((str(i), comment))
|
|
1156
|
+
|
|
1157
|
+
for key in range_items:
|
|
1158
|
+
section.pop(key)
|
|
1159
|
+
|
|
1160
|
+
for key, comm in added_items:
|
|
1161
|
+
section[key] = comm
|
|
1162
|
+
|
|
1163
|
+
if len(self.lut)>0 and len(section)>0:
|
|
1164
|
+
tmp = copy.deepcopy(section)
|
|
1165
|
+
section.clear()
|
|
1166
|
+
for key, val in tmp.items():
|
|
1167
|
+
section[self.convert_channel(key)] = val
|
|
1168
|
+
|
|
1169
|
+
|
|
786
1170
|
def save_test(self, *args):
|
|
787
1171
|
"""Save Test file."""
|
|
788
1172
|
dialog = Gtk.FileChooserDialog(
|
|
@@ -814,6 +1198,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
814
1198
|
data = {
|
|
815
1199
|
"institution": self.institute,
|
|
816
1200
|
"date": ITkDButils.get_db_date(),
|
|
1201
|
+
"runNumber": "1",
|
|
817
1202
|
"properties": {},
|
|
818
1203
|
"results": {},
|
|
819
1204
|
"comments": [],
|
|
@@ -843,7 +1228,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
843
1228
|
if len(values) == 4:
|
|
844
1229
|
SN, operator, machine = values
|
|
845
1230
|
else:
|
|
846
|
-
self.write_message("Something went wrong while requesting missing information
|
|
1231
|
+
self.write_message("Something went wrong while requesting missing information.\n")
|
|
847
1232
|
|
|
848
1233
|
data["component"] = SN
|
|
849
1234
|
data["properties"]["OPERATOR"] = operator
|
|
@@ -852,7 +1237,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
852
1237
|
data["institution"] = self.institute
|
|
853
1238
|
if data["runNumber"] == "-1":
|
|
854
1239
|
data["runNumber"] = "1"
|
|
855
|
-
|
|
1240
|
+
|
|
856
1241
|
data["date"] = self.date.get_text()
|
|
857
1242
|
|
|
858
1243
|
|
|
@@ -878,7 +1263,15 @@ class WireBond(dbGtkUtils.ITkDBWindow):
|
|
|
878
1263
|
|
|
879
1264
|
self.get_test_header(skeleton)
|
|
880
1265
|
self.get_list_of_channels(skeleton)
|
|
881
|
-
self.
|
|
1266
|
+
self.fix_list_of_channels(skeleton)
|
|
1267
|
+
try:
|
|
1268
|
+
self.get_unconnected(skeleton)
|
|
1269
|
+
self.compute_repaired(skeleton)
|
|
1270
|
+
self.compute_hybrid_to_pb(skeleton)
|
|
1271
|
+
self.compute_module_to_frame(skeleton)
|
|
1272
|
+
|
|
1273
|
+
except ValueError:
|
|
1274
|
+
return
|
|
882
1275
|
|
|
883
1276
|
uploadW = UploadTest.UploadTest(self.session, payload=skeleton)
|
|
884
1277
|
# uploadW.run()
|
|
@@ -895,7 +1288,7 @@ def main():
|
|
|
895
1288
|
|
|
896
1289
|
client.user_gui = dlg
|
|
897
1290
|
|
|
898
|
-
|
|
1291
|
+
|
|
899
1292
|
win = WireBond(client, title="WireBond")
|
|
900
1293
|
win.connect("destroy", Gtk.main_quit)
|
|
901
1294
|
win.show_all()
|
|
@@ -906,6 +1299,6 @@ def main():
|
|
|
906
1299
|
print("Arrrgggg!!!")
|
|
907
1300
|
|
|
908
1301
|
dlg.die()
|
|
909
|
-
|
|
1302
|
+
|
|
910
1303
|
if __name__ == "__main__":
|
|
911
1304
|
main()
|