itkdb-gtk 0.10.10.dev3__tar.gz → 0.10.10.dev5__tar.gz

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.

Files changed (40) hide show
  1. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/PKG-INFO +1 -1
  2. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ITkDButils.py +2 -1
  3. itkdb_gtk-0.10.10.dev5/itkdb_gtk/ModuleVisualInspection.py +247 -0
  4. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/PanelVisualInspection.py +2 -0
  5. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/UploadMultipleTests.py +53 -9
  6. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/UploadTest.py +5 -4
  7. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/WireBondGui.py +252 -147
  8. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/__init__.py +6 -1
  9. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/dashBoard.py +28 -6
  10. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/PKG-INFO +1 -1
  11. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/SOURCES.txt +1 -0
  12. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/entry_points.txt +1 -0
  13. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/pyproject.toml +2 -1
  14. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/README.md +0 -0
  15. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/CreateShipments.py +0 -0
  16. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/GetShipments.py +0 -0
  17. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/GlueWeight.py +0 -0
  18. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ITkDB.desktop +0 -0
  19. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ITkDB.svg +0 -0
  20. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ITkDBlogin.py +0 -0
  21. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/PetalReceptionTests.py +0 -0
  22. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/SensorUtils.py +0 -0
  23. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ShowAttachments.py +0 -0
  24. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ShowComments.py +0 -0
  25. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/ShowDefects.py +0 -0
  26. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/UploadModuleIV.py +0 -0
  27. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/UploadPetalInformation.py +0 -0
  28. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/dbGtkUtils.py +0 -0
  29. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/readAVSdata.py +0 -0
  30. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/readGoogleSheet.py +0 -0
  31. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk/untrash_component.py +0 -0
  32. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/dependency_links.txt +0 -0
  33. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/requires.txt +0 -0
  34. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/itkdb_gtk.egg-info/top_level.txt +0 -0
  35. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/setup.cfg +0 -0
  36. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/test/testAnimated.py +0 -0
  37. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/test/testBatch.py +0 -0
  38. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/test/testComponent.py +0 -0
  39. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/test/test_attachment.py +0 -0
  40. {itkdb_gtk-0.10.10.dev3 → itkdb_gtk-0.10.10.dev5}/test/test_holes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: itkdb_gtk
3
- Version: 0.10.10.dev3
3
+ Version: 0.10.10.dev5
4
4
  Summary: A collection of Gtk based GUI to access ITkDB.
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
@@ -350,7 +350,8 @@ def upload_test(client, data, attachments=None, check_runNumber=False):
350
350
  data=data,
351
351
  files=attachment)
352
352
  try:
353
- attachment_urls[path.name] = db_response['url']
353
+ url = db_response['url'].replace("https://eosatlas.cern.ch","https://cernbox.cern.ch/files/spaces")
354
+ attachment_urls[path.name] = url
354
355
 
355
356
  except KeyError:
356
357
  pass
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env python3
2
+ """Module Visual inspection GUI."""
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ try:
7
+ import itkdb_gtk
8
+
9
+ except ImportError:
10
+ cwd = Path(__file__).parent.parent
11
+ sys.path.append(cwd.as_posix())
12
+
13
+ from itkdb_gtk import dbGtkUtils, ITkDBlogin, ITkDButils
14
+ from itkdb_gtk.ShowComments import ShowComments
15
+ from itkdb_gtk.ShowDefects import ShowDefects
16
+ from itkdb_gtk.ShowAttachments import ShowAttachments
17
+ from itkdb_gtk.UploadTest import UploadTest
18
+
19
+ import gi
20
+ gi.require_version("Gtk", "3.0")
21
+ from gi.repository import Gtk, Gio
22
+
23
+ HELP_LINK="https://itkdb-gtk.docs.cern.ch/moduleVisualInspection.html"
24
+
25
+ class ModuleVisualInspection(dbGtkUtils.ITkDBWindow):
26
+ """Module Visual Inspection."""
27
+
28
+ def __init__(self, session, title="Module Visual Inspection", help_link=HELP_LINK):
29
+ super().__init__(title=title,
30
+ session=session,
31
+ show_search="Find object with given SN.",
32
+ help_link=help_link)
33
+
34
+ self.institute = self.pdb_user["institutions"][0]["code"]
35
+ self.global_image = None
36
+ self.global_link = None
37
+ self.data = None
38
+ self.attachments = []
39
+ self.comments = []
40
+ self.defects = []
41
+
42
+ # action button in header
43
+ button = Gtk.Button()
44
+ icon = Gio.ThemedIcon(name="document-send-symbolic")
45
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
46
+ button.add(image)
47
+ button.set_tooltip_text("Click to upload the test.")
48
+ button.connect("clicked", self.upload_test)
49
+ self.hb.pack_end(button)
50
+
51
+ grid = Gtk.Grid(column_spacing=5, row_spacing=5)
52
+ self.mainBox.pack_start(grid, False, False, 5)
53
+
54
+ irow = 0
55
+ receiver = self.create_institute_combo(only_user=True)
56
+ receiver.connect("changed", self.on_institute)
57
+ receiver.set_tooltip_text("Select the Institute making the test.")
58
+ dbGtkUtils.set_combo_iter(receiver, self.institute)
59
+
60
+ lbl = Gtk.Label(label="Institute")
61
+ lbl.set_xalign(0)
62
+ grid.attach(lbl, 0, irow, 1, 1)
63
+ grid.attach(receiver, 1, irow, 1, 1)
64
+
65
+ irow += 1
66
+ lbl = Gtk.Label(label="Serial Number")
67
+ lbl.set_xalign(0)
68
+ grid.attach(lbl, 0, irow, 1, 1)
69
+
70
+ self.SN = dbGtkUtils.TextEntry(small=True)
71
+ self.SN.connect("text_changed", self.SN_ready)
72
+ self.SN.widget.set_tooltip_text("Enter SN of module.")
73
+ grid.attach(self.SN.widget, 1, irow, 1, 1)
74
+
75
+ irow += 1
76
+ lbl = Gtk.Label(label="Date")
77
+ lbl.set_xalign(0)
78
+ grid.attach(lbl, 0, irow, 1, 1)
79
+
80
+ self.date = dbGtkUtils.TextEntry(small=True)
81
+ grid.attach(self.date.widget, 1, irow, 1, 1)
82
+ self.date.entry.set_text(ITkDButils.get_db_date())
83
+ self.date.connect("text_changed", self.new_date)
84
+
85
+ irow +=1
86
+ self.passed = Gtk.Switch()
87
+ self.passed.props.halign = Gtk.Align.START
88
+ self.passed.set_active(True)
89
+ lbl = Gtk.Label(label="Passed")
90
+ lbl.set_xalign(0)
91
+ grid.attach(lbl, 0, irow, 1, 1)
92
+ grid.attach(self.passed, 1, irow, 1, 1)
93
+
94
+ irow +=1
95
+ self.problems = Gtk.Switch()
96
+ self.problems.props.halign = Gtk.Align.START
97
+ self.problems.set_active(False)
98
+ lbl = Gtk.Label(label="Problems")
99
+ lbl.set_xalign(0)
100
+ grid.attach(lbl, 0, irow, 1, 1)
101
+ grid.attach(self.problems, 1, irow, 1, 1)
102
+
103
+
104
+ # The "Add attachment" button.
105
+ box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
106
+ self.mainBox.pack_start(box, False, False, 0)
107
+ self.btn_attch = dbGtkUtils.add_button_to_container(box, "Attachments",
108
+ "Click to edit attachments.",
109
+ self.edit_attachments)
110
+
111
+ self.btn_comments = dbGtkUtils.add_button_to_container(box, "Comments",
112
+ "Click to edit comments.",
113
+ self.edit_comments)
114
+
115
+ self.btn_defects = dbGtkUtils.add_button_to_container(box, "Defects",
116
+ "Click to edit defects.",
117
+ self.edit_defects)
118
+
119
+ self.mainBox.pack_start(self.message_panel.frame, True, True, 5)
120
+ self.write_message("Module Visual Inspection\n")
121
+ self.show_all()
122
+
123
+ dbGtkUtils.setup_scanner(self.get_qrcode)
124
+
125
+ def on_institute(self, combo):
126
+ """A new recipient has been chosen."""
127
+ name = self.get_institute_from_combo(combo)
128
+ if name:
129
+ self.institute = name
130
+
131
+ def new_date(self, entry, value):
132
+ """new date given at input."""
133
+ d = dbGtkUtils.parse_date_as_string(value)
134
+ if d is not None:
135
+ self.date.set_text(d)
136
+
137
+ def SN_ready(self, *args):
138
+ """SN is ready in the TextEnttry."""
139
+ SN = self.SN.get_text()
140
+ # GEt children.
141
+ module = ITkDButils.get_DB_component(self.session, SN)
142
+ if module is None:
143
+ self.write_message(ITkDButils.get_db_response())
144
+ return
145
+
146
+ SN = module["serialNumber"]
147
+ args[0].set_text(SN)
148
+
149
+
150
+ def edit_attachments(self, *args):
151
+ """Edit test attachmetns."""
152
+ SA = ShowAttachments("Test Attachments", self.session, self.attachments, parent=self)
153
+ response = SA.run()
154
+ if response == Gtk.ResponseType.OK:
155
+ self.attachments = SA.attachments
156
+
157
+ SA.hide()
158
+ SA.destroy()
159
+
160
+ if len(self.attachments) > 0:
161
+ self.btn_attch.set_label("Attachments ({})".format(len(self.attachments)))
162
+
163
+ def edit_comments(self, *args):
164
+ """Edit test comments."""
165
+ SC = ShowComments("Test Comments", self.comments, self)
166
+ rc = SC.run()
167
+ if rc == Gtk.ResponseType.OK:
168
+ self.comments = SC.comments
169
+
170
+ SC.hide()
171
+ SC.destroy()
172
+
173
+ if len(self.comments) > 0:
174
+ self.btn_comments.set_label("Comments ({})".format(len(self.comments)))
175
+
176
+ def edit_defects(self, *args):
177
+ """Edit test defects."""
178
+ SD = ShowDefects("Test Defects", self.defects, self)
179
+ rc = SD.run()
180
+ if rc == Gtk.ResponseType.OK:
181
+ self.defects = SD.defects
182
+
183
+ SD.hide()
184
+ SD.destroy()
185
+
186
+ if len(self.defects) > 0:
187
+ self.btn_defects.set_label("Defects ({})".format(len(self.defects)))
188
+
189
+ def upload_test(self, *args):
190
+ """Upload the test."""
191
+ SN = self.SN.get_text()
192
+ if len(SN) == 0:
193
+ dbGtkUtils.complain("Invalid Serial Number", SN)
194
+ return
195
+
196
+ defaults = {
197
+ "component": SN,
198
+ "institution": self.institute,
199
+ "passed": self.passed.get_active(),
200
+ "problems": self.problems.get_active(),
201
+ "runNumber": "1",
202
+ "date": self.date.get_text()
203
+ }
204
+ self.data = ITkDButils.get_test_skeleton(self.session,
205
+ "MODULE",
206
+ "VISUAL_INSPECTION",
207
+ defaults)
208
+
209
+ self.data["comments"] = self.comments
210
+ self.data["defects"] = self.defects
211
+ uploadW = UploadTest(self.session, self.data, self.attachments)
212
+
213
+
214
+
215
+ def get_qrcode(self, fd, state, reader):
216
+ """Read SN from scanner."""
217
+ txt = dbGtkUtils.scanner_get_line(reader)
218
+ self.write_message("SN: {}\n".format(txt))
219
+ self.SN_ready(txt, self.SN.widget)
220
+
221
+
222
+ def main():
223
+ """Main entry."""
224
+ # DB login
225
+ dlg = ITkDBlogin.ITkDBlogin()
226
+ client = dlg.get_client()
227
+ if client is None:
228
+ print("Could not connect to DB with provided credentials.")
229
+ dlg.die()
230
+ sys.exit()
231
+
232
+ client.user_gui = dlg
233
+
234
+ gTest = ModuleVisualInspection(client)
235
+
236
+ gTest.present()
237
+ gTest.connect("destroy", Gtk.main_quit)
238
+ try:
239
+ Gtk.main()
240
+
241
+ except KeyboardInterrupt:
242
+ print("Arrrgggg!!!")
243
+
244
+ dlg.die()
245
+
246
+ if __name__ == "__main__":
247
+ main()
@@ -546,6 +546,8 @@ class PanelVisualInspection(dbGtkUtils.ITkDBWindow):
546
546
  dbGtkUtils.complain("Failed adding global link as comment: {}-{}".format(payload["component"],
547
547
  payload["testType"]), msg)
548
548
  self.write_message(msg+"\n")
549
+ else:
550
+ self.write_message("Image: {}\n".format(global_link))
549
551
 
550
552
 
551
553
  n_items += 1
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python3
2
2
  """GUI to upload tests."""
3
- import argparse
4
3
  import fnmatch
5
4
  import json
6
5
  import os
@@ -64,7 +63,26 @@ def all_files(root, patterns='*', single_level=False, yield_folders=False):
64
63
 
65
64
 
66
65
  class TestList(object):
67
- SN, TestType, RunNumber, Date, Institute, Stage, currentStage, Path, Json, Nattch, Attachments, Ncomm, Comments, Ndef, Defects, ALL = range(16)
66
+ """Enumeration with TreeView model columns."""
67
+ (
68
+ SN,
69
+ TestType,
70
+ RunNumber,
71
+ Date,
72
+ Institute,
73
+ Stage,
74
+ currentStage,
75
+ Path,
76
+ Json,
77
+ Nattch,
78
+ Attachments,
79
+ Ncomm,
80
+ Comments,
81
+ Ndef,
82
+ Defects,
83
+ Color,
84
+ ALL,
85
+ ) = range(17)
68
86
 
69
87
 
70
88
  def check_data(data):
@@ -113,6 +131,7 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
113
131
  self.tests = []
114
132
  self.data = None
115
133
  self.tree = None
134
+ self.def_color = None
116
135
 
117
136
  self.init_window()
118
137
 
@@ -174,7 +193,23 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
174
193
 
175
194
  def create_tree_view(self, size=150):
176
195
  """Creates the tree vew with the attachments."""
177
- model = Gtk.ListStore(str, str, str, str, str, str, str, str, object, int, object, int, object, int, object)
196
+ model = Gtk.ListStore(str, # SN
197
+ str, # test type
198
+ str, # runNumber
199
+ str, # date
200
+ str, # institute
201
+ str, # stage
202
+ str, # stage
203
+ str, # ifile
204
+ object, # data
205
+ int, # num. attch.
206
+ object, # attachments
207
+ int, # num. comments
208
+ object, # comments
209
+ int, # num defects
210
+ object, # defects
211
+ str # color
212
+ )
178
213
  self.tree = Gtk.TreeView(model=model)
179
214
  self.tree.connect("button-press-event", self.button_pressed)
180
215
  scrolled = Gtk.ScrolledWindow()
@@ -187,7 +222,8 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
187
222
  self.tree.append_column(column)
188
223
 
189
224
  renderer = Gtk.CellRendererText()
190
- column = Gtk.TreeViewColumn("Test Type", renderer, text=TestList.TestType)
225
+ self.def_color = renderer.get_property("foreground-rgba").to_string()
226
+ column = Gtk.TreeViewColumn("Test Type", renderer, text=TestList.TestType, foreground=TestList.Color)
191
227
  self.tree.append_column(column)
192
228
 
193
229
  renderer = Gtk.CellRendererText()
@@ -376,7 +412,7 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
376
412
  """Set the test stage."""
377
413
  model, lv_iter, val = data
378
414
  SN = val[TestList.SN]
379
- combo, currentStage = self.get_component_stages(SN)
415
+ combo, _ = self.get_component_stages(SN)
380
416
 
381
417
  dlg = Gtk.Dialog(title="Add Attachment")
382
418
 
@@ -429,7 +465,7 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
429
465
  return combo, currentStage
430
466
 
431
467
  except Exception:
432
- self.write_message("Something went wring with the stages")
468
+ self.write_message("Something went wrong with the stages\n")
433
469
  return [None, None]
434
470
 
435
471
  def add_tests_to_view(self, files):
@@ -473,8 +509,8 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
473
509
  path = folder / path.name
474
510
 
475
511
  if path.exists():
476
- attachments.append(ITkDButils.Attachment(path=path,
477
- title=att["title"],
512
+ attachments.append(ITkDButils.Attachment(path=path,
513
+ title=att["title"],
478
514
  desc=att["description"]))
479
515
  else:
480
516
  self.write_message("Ignoring atachment {}".format(data["path"]))
@@ -487,10 +523,18 @@ class UploadMultipleTests(dbGtkUtils.ITkDBWindow):
487
523
  defects = data.get("defects", [])
488
524
  the_date = handle_test_date(data["date"])
489
525
  combo, currentStage = self.get_component_stages(data["component"])
526
+ if data["passed"]:
527
+ if data["problems"]:
528
+ color = "orange"
529
+ else:
530
+ color = self.def_color
531
+ else:
532
+ color = "firebrick"
533
+
490
534
  model.append([data["component"], data["testType"], data["runNumber"], the_date,
491
535
  data["institution"], currentStage, currentStage,
492
536
  ifile, data, len(attachments), attachments,
493
- len(comments), comments, len(defects), defects])
537
+ len(comments), comments, len(defects), defects, color])
494
538
 
495
539
  except Exception as E:
496
540
  self.write_message("Cannot load file {}\n".format(ifile))
@@ -9,7 +9,6 @@ try:
9
9
  import itkdb_gtk
10
10
 
11
11
  except ImportError:
12
- from pathlib import Path
13
12
  cwd = Path(__file__).parent.parent
14
13
  sys.path.append(cwd.as_posix())
15
14
 
@@ -93,6 +92,7 @@ class UploadTest(dbGtkUtils.ITkDBWindow):
93
92
  self.attachments = []
94
93
  self.comments = []
95
94
  self.defects = []
95
+ self.currentStage = None
96
96
  if attachment is not None:
97
97
  if isinstance(attachment, ITkDButils.Attachment):
98
98
  if attachment.path is not None:
@@ -219,6 +219,7 @@ class UploadTest(dbGtkUtils.ITkDBWindow):
219
219
  except TypeError:
220
220
  self.load_payload(self.payload)
221
221
  self.write_message("Loaded memory payload.\n")
222
+ self.testF.set_sensitive(False)
222
223
 
223
224
  if len(self.attachments) > 0:
224
225
  self.btn_attch.set_label("Attachments ({})".format(len(self.attachments)))
@@ -293,7 +294,7 @@ class UploadTest(dbGtkUtils.ITkDBWindow):
293
294
  self.objStage.set_active(indx)
294
295
 
295
296
  except Exception:
296
- self.write_message("Something went wring with the stages")
297
+ self.write_message("Something went wrong with the stages\n")
297
298
 
298
299
 
299
300
  def on_test_file(self, fdlg):
@@ -303,7 +304,7 @@ class UploadTest(dbGtkUtils.ITkDBWindow):
303
304
 
304
305
  # The file exists by definition
305
306
  try:
306
- self.data = json.loads(open(fnam).read())
307
+ self.data = json.loads(open(fnam, encoding="UTF-8").read())
307
308
  errors, missing = check_data(self.data)
308
309
  self.complete_missing(missing, errors)
309
310
  self.set_stages()
@@ -326,7 +327,7 @@ class UploadTest(dbGtkUtils.ITkDBWindow):
326
327
  self.write_message("Setting Institution to {}\n".format(self.data["institution"]))
327
328
 
328
329
  else:
329
- dbGtkUtils.complain("Invalid JSON data".format('\n'.join(errors)))
330
+ dbGtkUtils.complain("Invalid JSON data\n{}".format('\n'.join(errors)))
330
331
 
331
332
  self.find_attachments()
332
333
  self.find_comments()
@@ -6,6 +6,7 @@ import re
6
6
  import json
7
7
  import copy
8
8
  from pathlib import Path
9
+ from collections import namedtuple
9
10
  import gi
10
11
 
11
12
  gi.require_version("Gtk", "3.0")
@@ -28,18 +29,6 @@ from itkdb_gtk import ITkDBlogin, ITkDButils, UploadTest
28
29
  #valid_channel = re.compile("(^[0-9]+)-([0-9]+)")
29
30
  valid_channel = re.compile("^[0-9]+[\\s*\\,\\s,-[0-9]+]*")
30
31
 
31
- def range_to_list(V):
32
- """Convert a range (ch1-ch2) to a list."""
33
- if '-' not in V:
34
- return [V]
35
-
36
- out = []
37
- endpoints = list(map(int, V.split('-')))
38
- endpoints.sort()
39
- for i in range(endpoints[0], endpoints[1]+1):
40
- out.append(str(i))
41
-
42
- return out
43
32
 
44
33
  test_parameters = {
45
34
  "Repaired Row 1": "REPAIRED_FRONTEND_ROW1",
@@ -103,21 +92,31 @@ module_param = {
103
92
  ],
104
93
  }
105
94
 
106
- def wire2strip(mod_par, irow, iwire):
107
- """Convert from wirebond index to strip_number."""
108
- for sensor in mod_par:
109
- for hyb in sensor:
110
- rng = hyb[irow]
111
- if iwire>= rng[0] and iwire<=rng[1]:
112
- if irow % 2:
113
- ichan = 2*(iwire-rng[0]) + 1
114
- else:
115
- ichan = 2*(iwire-rng[0])
95
+ def range_to_list(V):
96
+ """Convert a range (ch1-ch2) to a list."""
97
+ if '-' not in V and ',' not in V:
98
+ return [V]
116
99
 
117
- return ichan
100
+ out = []
101
+ values = V.split(',')
102
+ for V in values:
103
+ if '-' in V:
104
+ endpoints = list(map(int, V.split('-')))
105
+ endpoints.sort()
106
+ for i in range(endpoints[0], endpoints[1]+1):
107
+ out.append(str(i))
108
+ else:
109
+ out.append(V)
110
+
111
+ return out
118
112
 
119
- return None
113
+ def count_items(items):
114
+ """Count number of channels from results."""
115
+ nitems = 0
116
+ for key in items.keys():
117
+ nitems += len(range_to_list(key))
120
118
 
119
+ return nitems
121
120
 
122
121
  def find_holes(chan_list, min_chan=0, max_chan=999999):
123
122
  """Find groups of consecutive channels."""
@@ -161,19 +160,41 @@ def find_holes(chan_list, min_chan=0, max_chan=999999):
161
160
  return holes
162
161
 
163
162
 
163
+ def wire2strip(iwire, irow, first_chan):
164
+ """From bond to strip number."""
165
+ if irow % 2:
166
+ istrip = 2*(iwire-first_chan) + 1
167
+ else:
168
+ istrip = 2*(iwire-first_chan)
169
+
170
+ return istrip
171
+
172
+
173
+ class Hole:
174
+ """A range of consecutive unconnected channels."""
175
+ def __init__(self, *args):
176
+ for i, name in enumerate(['sensor', 'hybrid', 'row', 'chan', 'width']):
177
+ setattr(self, name, args[i])
178
+
179
+ def __repr__(self):
180
+ return "sensor: {} hyb: {} row: {} chan: {} width: {}".format(
181
+ self.sensor, self.hybrid, self.row, self.chan, self.width
182
+ )
183
+
164
184
  class HybridHoles:
165
- """Holes in hybrid bomds.
185
+ """Holes in hybrid bonds.
166
186
 
167
187
  Holes are defined by a list [first_chan, n_chan].
168
188
  """
169
189
 
170
- def __init__(self, param, hid=0):
190
+ def __init__(self, param, win=None, hid=0):
171
191
  """Initialization.
172
192
 
173
193
  Args:
174
194
  param: Hybrid wirebon parameters.
175
195
 
176
196
  """
197
+ self.win = win
177
198
  self.id = hid
178
199
  self.param = param
179
200
  self.nchan = 0
@@ -182,12 +203,25 @@ class HybridHoles:
182
203
 
183
204
  self.holes = [[] for irow in range(4)]
184
205
  self.channels = [[] for irow in range(4)]
206
+ # Sensor strips for each of the strip rows "served" by a hybrid.
207
+ self.sensor_channels = [[], []]
208
+ self.sensor_holes = [[], []]
209
+
210
+ def ready(self):
211
+ """Call when all channels are in."""
212
+ for irow, C in enumerate(self.channels):
213
+ C.sort()
214
+ self.holes[irow] = find_holes(C)
215
+
216
+ for irow, S in enumerate(self.sensor_channels):
217
+ S.sort()
218
+ self.sensor_holes[irow] = find_holes(S)
185
219
 
186
220
  def add_channel(self, irow, ichan)->bool:
187
221
  """Add a new channel in row.
188
222
 
189
223
  Args:
190
- irow: rown number
224
+ irow: row number
191
225
  ichan: channel number
192
226
 
193
227
  Returns:
@@ -196,102 +230,93 @@ class HybridHoles:
196
230
  """
197
231
  first_chan = self.param[irow][0]
198
232
  last_chan = self.param[irow][1]
233
+ strip_row = int(irow/2)
234
+
235
+
199
236
  if isinstance(ichan, list) or isinstance(ichan, tuple):
200
237
  nadded = 0
201
238
  for ich in ichan:
202
- if ich >= first_chan and ich <= last_chan:
239
+ if first_chan <= ich <= last_chan:
203
240
  self.channels[irow].append(ich)
204
241
  nadded += 1
205
242
 
206
243
  self.channels[irow] = sorted(self.channels[irow])
244
+ for iwire in self.channels[irow]:
245
+ istrip = wire2strip(iwire, irow, first_chan)
246
+ self.sensor_channels[strip_row].append(istrip)
247
+
207
248
  return nadded>0
208
- else:
209
- if ichan >= first_chan and ichan <= last_chan:
210
- self.channels[irow].append(ichan)
211
- return True
212
- else:
213
- return False
214
249
 
215
- def get_n_unconnected(self):
250
+ if first_chan <= ichan <= last_chan:
251
+ self.channels[irow].append(ichan)
252
+ istrip = wire2strip(ichan, irow, first_chan)
253
+ self.sensor_channels[strip_row].append(istrip)
254
+ return True
255
+
256
+ return False
257
+
258
+ def get_n_unconnected(self) -> list:
216
259
  """Count number of unconnected channels.
217
260
 
218
261
  Return a list, one item per row.
219
262
  """
220
- nchan = []
221
- for row in self.holes:
222
- nch = 0
223
- for h in row:
224
- nch += h[1]
225
-
226
- nchan.append(nch)
227
-
263
+ nchan = [len(C) for C in self.channels]
228
264
  return nchan
229
265
 
230
- def get_max_consecutive(self):
231
- """Returns the largest 'hole'."""
266
+ def get_max_consecutive_from_list(self, holes):
267
+ """Return max widht of holes."""
232
268
  mx_width = []
269
+ lst_holes = []
270
+ for irow, row in enumerate(holes):
271
+ if len(row) == 0:
272
+ mxW = 0
233
273
 
234
- for row in self.holes:
235
- mxW = -1
236
- for h in row:
237
- if h[1] > mxW:
238
- mxW = h[1]
274
+ else:
275
+ mxW = -1
276
+ for h in row:
277
+ lst_holes.append(Hole(0, self.id, irow, h[0], h[1]))
278
+ mxW = max(mxW, h[1])
239
279
 
240
280
  mx_width.append(mxW)
241
281
 
242
- return mx_width
243
-
244
- def get_sensor_holes(self):
245
- """Compute holes in 'sensor' strips.
246
-
247
- Each hybrid has 2 sensor segments corresponding to
248
- rows (1,2) and (3, 4).
249
-
250
- Return a list of [sensor, hybrid, segment, ichan, width]
251
- """
252
- holes = []
253
- channels = [[], []]
254
- for irow, row in enumerate(self.channels):
255
- isegment = int(irow/2)
256
- for ich in row:
257
- rng = self.param[irow]
258
- if irow % 2:
259
- chan = 2*(ich-rng[0]) + 1
260
- else:
261
- chan = 2*(ich-rng[0])
262
-
263
- channels[isegment].append(chan)
282
+ return mx_width, lst_holes
264
283
 
265
- channels[isegment] = sorted(channels[isegment])
266
284
 
267
- for isegment, S in enumerate(channels):
268
- H = find_holes(S)
269
- if len(H)>0:
270
- out = [ [0, self.id, isegment, chan, width] for chan, width in H ]
271
- holes.extend(out)
272
-
273
- return holes
285
+ def get_max_consecutive(self):
286
+ """Returns the largest 'hole'."""
287
+ mx_width, _ = self.get_max_consecutive_from_list(self.holes)
288
+ return mx_width
274
289
 
290
+ def get_max_sensor_consecutive(self):
291
+ """Return largest hole in sensor."""
292
+ mx_width, holes = self.get_max_consecutive_from_list(self.sensor_holes)
293
+ return mx_width, holes
275
294
 
276
295
  class SensorHoles:
277
296
  """Holes in sensor."""
278
297
 
279
- def __init__(self, param, sid=0):
298
+ def __init__(self, param, win=None, sid=0):
280
299
  """Initialization.
281
300
 
282
301
  Args:
283
302
  param: sensor wirebon params
284
303
  """
304
+ self.win = win
285
305
  self.id = sid
286
306
  self.param = param
287
307
  self.nchan = 0
288
308
  self.nhybrid = len(param)
289
309
  self.hybrids = []
290
310
  for i, P in enumerate(param):
291
- H = HybridHoles(P, hid=i)
311
+ H = HybridHoles(P, hid=i, win=win)
292
312
  self.hybrids.append(H)
293
313
  self.nchan += H.nchan
294
314
 
315
+ def ready(self):
316
+ """Call when all channels are in."""
317
+ for H in self.hybrids:
318
+ H.ready()
319
+
295
320
  def get_n_hyb(self):
296
321
  """Return number of hybrids."""
297
322
  return len(self.hybrids)
@@ -305,15 +330,30 @@ class SensorHoles:
305
330
 
306
331
  This is ordered by row.
307
332
  """
308
- mx_width = [0, 0, 0, 0]
333
+ n_strip_row = 2*len(self.hybrids)
334
+ mx_width = [0 for x in range(n_strip_row)]
309
335
  for hyb in self.hybrids:
310
336
  mxW = hyb.get_max_consecutive()
311
337
  for j in range(4):
312
- if mxW[j] > mx_width[j]:
313
- mx_width[j] = mxW[j]
338
+ mx_width[j] = max(mx_width[j] , mxW[j])
314
339
 
315
340
  return mx_width
316
341
 
342
+ def get_max_sensor_consecutive(self):
343
+ """MAx widht of holes in sensor."""
344
+ mx_width = -1
345
+ holes = []
346
+ for hyb in self.hybrids:
347
+ mxW, hyb_holes = hyb.get_max_sensor_consecutive()
348
+ for H in hyb_holes:
349
+ H.sensor = self.id
350
+
351
+ holes.extend(hyb_holes)
352
+ for v in mxW:
353
+ mx_width = max(mx_width, v)
354
+
355
+ return mx_width, holes
356
+
317
357
  def get_n_unconnected(self):
318
358
  """Count number of unconnected channels.
319
359
 
@@ -327,37 +367,30 @@ class SensorHoles:
327
367
 
328
368
  return nchan
329
369
 
330
- def get_sensor_holes(self):
331
- """Return holes sensor.
332
-
333
- Return a list of [sensor, hybrid, segment, ichan, width]
334
- """
335
- holes = []
336
- for hyb in self.hybrids:
337
- H = hyb.get_sensor_holes()
338
- for _, ih, isegment, ichan, width in H:
339
- holes.append([self.id, ih, isegment, ichan, width])
340
-
341
- return holes
342
-
343
370
 
344
371
  class ModuleHoles:
345
372
  """Holes in Modules."""
346
373
 
347
- def __init__(self, param):
374
+ def __init__(self, param, win=None):
348
375
  """Initialization.
349
376
 
350
377
  Args:
351
378
  param: module wirebond params
352
379
  """
380
+ self.win = win
353
381
  self.nsensor = len(param)
354
382
  self.nchan = 0
355
383
  self.sensors = []
356
384
  for i, P in enumerate(param):
357
- S = SensorHoles(P, sid=i)
385
+ S = SensorHoles(P, sid=i, win=win)
358
386
  self.sensors.append(S)
359
387
  self.nchan += S.nchan
360
388
 
389
+ def ready(self):
390
+ """Call when all channels are in."""
391
+ for S in self.sensors:
392
+ S.ready()
393
+
361
394
  def get_max_consecutive(self):
362
395
  """Max number of consecutive unconnected channels.
363
396
 
@@ -367,22 +400,21 @@ class ModuleHoles:
367
400
  for S in self.sensors:
368
401
  mxW = S.get_max_consecutive()
369
402
  for j in range(4):
370
- if mxW[j] > mx_width[j]:
371
- mx_width[j] = mxW[j]
403
+ mx_width[j] = max(mx_width[j], mxW[j])
372
404
 
373
405
  return mx_width
374
406
 
375
- def get_sensor_holes(self) -> list:
376
- """Return. holesin sensor strips.
377
-
378
- Return a list of [sensor, hybrid, segment, ichan, width]
379
- """
380
- holes = []
407
+ def get_max_sensor_consecutive(self):
408
+ """The maximum number of consecutive channels per strip row."""
409
+ mx_width = -1
410
+ module_holes = []
381
411
  for S in self.sensors:
382
- for _, ihyb, isegment, ichan, width in S.get_sensor_holes():
383
- holes.append([S.id, ihyb, isegment, ichan, width])
412
+ width, holes = S.get_max_sensor_consecutive()
413
+ module_holes.extend(holes)
414
+ mx_width = max(mx_width, width)
415
+
416
+ return mx_width, module_holes
384
417
 
385
- return holes
386
418
 
387
419
  def get_n_unconnected(self) -> list:
388
420
  """Count number of unconnected channels.
@@ -575,12 +607,35 @@ class WireBond(dbGtkUtils.ITkDBWindow):
575
607
  lut = {}
576
608
  module_map = {}
577
609
  section = None
610
+ i_local = 0
611
+ i_std = 1
612
+ indx = ["local", "standard"]
613
+ found_format = False
578
614
  with open(fnam, 'r', encoding="UTF-8") as fin:
579
615
  for line in fin:
580
616
  line = line.strip()
581
617
 
582
618
  # Remove comments.
583
619
  ipos = line.find('#')
620
+ jpos = line.find("#!")
621
+ if jpos>=0 and ipos==jpos:
622
+ if found_format:
623
+ dbGtkUtils.complain("A second format line was found.",
624
+ "Onely one is allowed. stopr map parsing.")
625
+ return
626
+
627
+ indx = [x.lower() for x in line[ipos+2:].split()]
628
+ try:
629
+ i_local = indx.index("local")
630
+ i_std = indx.index("standard")
631
+ found_format = True
632
+ except ValueError:
633
+ dbGtkUtils.complain("Wrong format desciption string.",
634
+ "The words 'local' and 'standard' should be there.\n{}".format(line))
635
+ return
636
+
637
+ continue
638
+
584
639
  if ipos >= 0:
585
640
  line = line[:ipos].strip()
586
641
 
@@ -602,13 +657,13 @@ class WireBond(dbGtkUtils.ITkDBWindow):
602
657
  if section is None:
603
658
  continue
604
659
 
605
- values = list(map(str.strip, line.split(',')))
606
- if len(values)!=2:
660
+ values = line.split()
661
+ if len(values)!=len(indx):
607
662
  dbGtkUtils.complain("Cannot read Lookup table.", "Wrong line format: {}".format(line))
608
663
  return
609
664
 
610
- v_local = range_to_list(values[0])
611
- v_std = range_to_list(values[1])
665
+ v_local = range_to_list(values[i_local])
666
+ v_std = range_to_list(values[i_std])
612
667
 
613
668
  if len(v_local) != len(v_std):
614
669
  dbGtkUtils.complain("Wrong Lookup table.",
@@ -669,7 +724,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
669
724
  view_model = self.models[param]
670
725
  self.tree.set_model(view_model)
671
726
  else:
672
- self.write_message("Cannot find model for {}".format(param))
727
+ self.write_message("Cannot find model for {}\n".format(param))
673
728
 
674
729
  def create_combo(self):
675
730
  """Create the combo."""
@@ -813,7 +868,42 @@ class WireBond(dbGtkUtils.ITkDBWindow):
813
868
  self.hide()
814
869
  self.destroy()
815
870
 
816
- def compute_unconnected(self):
871
+ def compute_repaired(self, skeleton):
872
+ """Compute number of repaired."""
873
+ nrepaired = 0
874
+ for key, values in skeleton["results"].items():
875
+ if key.find("REPAIRED")<0 or key.find("ROW")<0:
876
+ continue
877
+
878
+ nrepaired += len(values)
879
+
880
+ if nrepaired>0:
881
+ skeleton["problems"] = True
882
+ skeleton["comments"].append("Number of repaired FE bonds: {}".format(nrepaired))
883
+
884
+ return nrepaired
885
+
886
+ def compute_hybrid_to_pb(self, skeleton):
887
+ """Compute number of failures and repairs."""
888
+ n = count_items(skeleton["results"]["REPAIRED_HYBRID_TO_PB"])
889
+ n = count_items(skeleton["results"]["FAILED_HYBRID_TO_PB"])
890
+ if n:
891
+ msg = "Hybrid to PB: {} failing bonds.".format(n)
892
+ skeleton["comments"].append(msg)
893
+ skeleton["passed"] = False
894
+ self.write_message("{}\n".format(msg))
895
+
896
+ def compute_module_to_frame(self, skeleton):
897
+ """Compute number of failures and repairs."""
898
+ n = count_items(skeleton["results"]["REPAIRED_MODULE_TO_FRAME"])
899
+ n = count_items(skeleton["results"]["FAILED_MODULE_TO_FRAME"])
900
+ if n:
901
+ msg = "Module to test frame: {} failing bonds.".format(n)
902
+ skeleton["comments"].append(msg)
903
+ skeleton["passed"] = False
904
+ self.write_message("{}\n".format(msg))
905
+
906
+ def compute_unconnected(self, results):
817
907
  """Compute number of unconnected."""
818
908
  try:
819
909
  param = get_module_param(self.SN.get_text())
@@ -821,9 +911,9 @@ class WireBond(dbGtkUtils.ITkDBWindow):
821
911
  dbGtkUtils.complain("Wrong SN number", str(E))
822
912
  return None
823
913
 
824
- M = ModuleHoles(param=param)
914
+ M = ModuleHoles(param=param, win=self)
825
915
 
826
- for test in test_parameters.values():
916
+ for test, values in results.items():
827
917
  if test.find("FAILED") < 0:
828
918
  continue
829
919
  if test.find("ROW") < 0:
@@ -832,16 +922,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
832
922
  irow = int(test[-1]) - 1
833
923
 
834
924
  # Get list of all channels with wirebond notation.
835
- model = self.models[test]
836
- it = model.get_iter_first()
837
- out = []
838
- while it:
839
- chan, _ = model[it]
840
- if len(chan) > 0:
841
- out.append(int(chan))
842
-
843
- it = model.iter_next(it)
844
-
925
+ out = [int(x) for x in values.keys()]
845
926
  # Translate to sensor, hybrids, etc.
846
927
  for S in M.sensors:
847
928
  for H in S.hybrids:
@@ -850,41 +931,66 @@ class WireBond(dbGtkUtils.ITkDBWindow):
850
931
 
851
932
 
852
933
  # Now get sensor strips.
934
+ M.ready()
853
935
  unconnected = M.get_n_unconnected()
854
936
  mx_consecutive = M.get_max_consecutive()
855
- module_holes = M.get_sensor_holes()
937
+ mx_sensor_width, module_holes = M.get_max_sensor_consecutive()
856
938
 
857
939
  out = {}
940
+ out["comments"] = []
941
+ out["defects"] = []
858
942
  for irow in range(4):
859
943
  key = "MAX_CONT_UNCON_ROW{}".format(irow+1)
860
944
  out[key] = mx_consecutive[irow]
861
945
 
862
- mxW = 0
863
946
  self.write_message("Found {} clusters of unconnected strips in sensor.\n".format(len(module_holes)))
864
947
  for H in module_holes:
865
- self.write_message("{}\n".format(str(H)))
866
- if H[-1] > mxW:
867
- mxW = H[-1]
948
+ self.write_message("{}\n".format(H))
868
949
 
869
- if mxW > 0:
870
- self.write_message("Max width: {}". format(mxW))
950
+ if mx_sensor_width > 0:
951
+ self.write_message("Max width of consecutive unconnected strips: {}\n". format(mx_sensor_width))
952
+
953
+ out["MAX_UNCON_SENSOR_CHAN"] = mx_sensor_width
954
+ if mx_sensor_width > 8:
955
+ out["passed"] = False
956
+ out["comments"].append("Too many consecutive sensor strips unconnected: {}".format(mx_sensor_width))
871
957
 
872
- out["MAX_UNCON_SENSOR_CHAN"] = mxW
873
958
  nstrips = 0
874
959
  for v in unconnected:
875
960
  nstrips += v
876
961
 
877
- out["TOTAL_PERC_UNCON_SENSOR_CHAN"] = nstrips/M.nchan
962
+ percent = 100*nstrips/M.nchan
963
+ out["TOTAL_PERC_UNCON_SENSOR_CHAN"] = percent
964
+ if out["TOTAL_PERC_UNCON_SENSOR_CHAN"] > 1.0:
965
+ out["passed"] = False
966
+ out["comments"].append("More than 1%% of channels unconnected: {:.1f}%%".format(percent))
878
967
 
879
968
  return out
880
969
 
881
970
  def get_unconnected(self, skeleton):
882
971
  """Fill the test DTO with unconnected information."""
883
- out = self.compute_unconnected()
972
+ out = self.compute_unconnected(skeleton["results"])
884
973
  if out is None:
885
974
  raise ValueError("Wrong SN")
886
975
 
887
976
  for key, val in out.items():
977
+ if key in ["passed", "problems"]:
978
+ skeleton[key] = out[key]
979
+ continue
980
+
981
+ if key == "comments":
982
+ for C in out[key]:
983
+ skeleton[key].append(C)
984
+
985
+ continue
986
+
987
+ if key == "defects":
988
+ for D in out[key]:
989
+ skeleton[key].append(D)
990
+
991
+ continue
992
+
993
+
888
994
  skeleton["results"][key] = val
889
995
 
890
996
  def read_file(self, *args):
@@ -921,7 +1027,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
921
1027
  try:
922
1028
  dbGtkUtils.set_combo_iter(self.inst_combo, data["institution"])
923
1029
  except KeyError:
924
- self.write_message("institution value is not in the loaded file.")
1030
+ self.write_message("institution value is not in the loaded file\n.")
925
1031
 
926
1032
  self.operator.set_text(data["properties"]["OPERATOR"])
927
1033
  self.machine.set_text(data["properties"]["BOND_MACHINE"])
@@ -971,12 +1077,8 @@ class WireBond(dbGtkUtils.ITkDBWindow):
971
1077
  continue
972
1078
 
973
1079
  for V in values:
974
- if '-' in V:
975
- for i in range_to_list(V):
976
- added_items.append((str(i), comment))
977
-
978
- elif len(V)>0:
979
- added_items.append((V, comment))
1080
+ for i in range_to_list(V):
1081
+ added_items.append((str(i), comment))
980
1082
 
981
1083
  for key in range_items:
982
1084
  section.pop(key)
@@ -1052,7 +1154,7 @@ class WireBond(dbGtkUtils.ITkDBWindow):
1052
1154
  if len(values) == 4:
1053
1155
  SN, operator, machine = values
1054
1156
  else:
1055
- self.write_message("Something went wrong while requesting missing information.")
1157
+ self.write_message("Something went wrong while requesting missing information.\n")
1056
1158
 
1057
1159
  data["component"] = SN
1058
1160
  data["properties"]["OPERATOR"] = operator
@@ -1090,6 +1192,9 @@ class WireBond(dbGtkUtils.ITkDBWindow):
1090
1192
  self.fix_list_of_channels(skeleton)
1091
1193
  try:
1092
1194
  self.get_unconnected(skeleton)
1195
+ self.compute_repaired(skeleton)
1196
+ self.compute_hybrid_to_pb(skeleton)
1197
+ self.compute_module_to_frame(skeleton)
1093
1198
 
1094
1199
  except ValueError:
1095
1200
  return
@@ -1,6 +1,6 @@
1
1
  """ itkdb-gtk python module
2
2
  """
3
- __version__ = "0.10.10.dev3"
3
+ __version__ = "0.10.10.dev5"
4
4
 
5
5
 
6
6
  def dash_board():
@@ -62,3 +62,8 @@ def panelVisualInspection():
62
62
  """Visual inspection of PWB or HYB panels."""
63
63
  from .PanelVisualInspection import main
64
64
  main()
65
+
66
+ def moduleVisualInspection():
67
+ """Visual inspection of Modules."""
68
+ from .ModuleVisualInspection import main
69
+ main()
@@ -22,6 +22,7 @@ from itkdb_gtk import GlueWeight
22
22
  from itkdb_gtk import UploadModuleIV
23
23
  from itkdb_gtk import WireBondGui
24
24
  from itkdb_gtk import PanelVisualInspection
25
+ from itkdb_gtk import ModuleVisualInspection
25
26
 
26
27
 
27
28
  HAS_PETALQC=False
@@ -53,8 +54,9 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
53
54
  MOD_IV = 7
54
55
  WIRE_BOND = 8
55
56
  PANEL_VI = 9
56
- PETAL_CORE_METRO = 10
57
- PETAL_CORE_THERMAL = 11
57
+ MODULE_VI = 10
58
+ PETAL_CORE_METRO = 11
59
+ PETAL_CORE_THERMAL = 12
58
60
 
59
61
 
60
62
  def __init__(self, session):
@@ -107,9 +109,13 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
107
109
  grid.attach(btnWireBond, 1, irow, 1, 1)
108
110
 
109
111
  irow += 1
110
- btnModIV = Gtk.Button(label="Panel Visual Insp.")
111
- btnModIV.connect("clicked", self.panel_VI)
112
- grid.attach(btnModIV, 0, irow, 1, 1)
112
+ btnPanelVI = Gtk.Button(label="Panel Visual Insp.")
113
+ btnPanelVI.connect("clicked", self.panel_VI)
114
+ grid.attach(btnPanelVI, 1, irow, 1, 1)
115
+
116
+ btnModVI = Gtk.Button(label="Module Visual Insp.")
117
+ btnModVI.connect("clicked", self.module_VI)
118
+ grid.attach(btnModVI, 0, irow, 1, 1)
113
119
 
114
120
 
115
121
  if HAS_PETALQC:
@@ -242,7 +248,23 @@ class DashWindow(dbGtkUtils.ITkDBWindow):
242
248
  return
243
249
 
244
250
  self.mask |= bt
245
- W = PanelVisualInspection.PanelVisualInspection(session=self.session, title="Panel Visual Inspection", help_link=HELP_LINK)
251
+ W = PanelVisualInspection.PanelVisualInspection(session=self.session,
252
+ title="Panel Visual Inspection",
253
+ help_link=HELP_LINK)
254
+ W.connect("destroy", self.app_closed, bitn)
255
+ W.show_all()
256
+
257
+ def module_VI(self, *args):
258
+ """Panel VI tests."""
259
+ bitn = DashWindow.MODULE_VI
260
+ bt = 1 << bitn
261
+ if self.mask & bt:
262
+ return
263
+
264
+ self.mask |= bt
265
+ W = ModuleVisualInspection.ModuleVisualInspection(session=self.session,
266
+ title="Module Visual Inspection",
267
+ help_link=HELP_LINK)
246
268
  W.connect("destroy", self.app_closed, bitn)
247
269
  W.show_all()
248
270
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: itkdb_gtk
3
- Version: 0.10.10.dev3
3
+ Version: 0.10.10.dev5
4
4
  Summary: A collection of Gtk based GUI to access ITkDB.
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
@@ -7,6 +7,7 @@ itkdb_gtk/ITkDB.desktop
7
7
  itkdb_gtk/ITkDB.svg
8
8
  itkdb_gtk/ITkDBlogin.py
9
9
  itkdb_gtk/ITkDButils.py
10
+ itkdb_gtk/ModuleVisualInspection.py
10
11
  itkdb_gtk/PanelVisualInspection.py
11
12
  itkdb_gtk/PetalReceptionTests.py
12
13
  itkdb_gtk/SensorUtils.py
@@ -3,6 +3,7 @@ createShipments = itkdb_gtk:createShipments
3
3
  getShipments = itkdb_gtk:getShipments
4
4
  glueWeight = itkdb_gtk:glueWeight
5
5
  itkdb_dashBoard = itkdb_gtk:dash_board
6
+ moduleVisualInspection = itkdb_gtk:moduleVisualInspection
6
7
  panelVisualInspection = itkdb_gtk:panelVisualInspection
7
8
  petalReceptionTests = itkdb_gtk:petalReceptionTests
8
9
  uploadModuleIV = itkdb_gtk:uploadModuleIV
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "itkdb_gtk"
7
- version = "0.10.10.dev3"
7
+ version = "0.10.10.dev5"
8
8
  authors = [
9
9
  { name="Carlos Lacasta", email="carlos.lacasta@cern.ch" },
10
10
  ]
@@ -38,6 +38,7 @@ uploadModuleIV = "itkdb_gtk:uploadModuleIV"
38
38
  wirebondTest = "itkdb_gtk:wirebondTest"
39
39
  uploadPetalInformation = "itkdb_gtk:uploadPetalInformation"
40
40
  panelVisualInspection = "itkdb_gtk:panelVisualInspection"
41
+ moduleVisualInspection = "itkdb_gtk:moduleVisualInspection"
41
42
 
42
43
  [tool.setuptools]
43
44
  include-package-data = true