itkdb-gtk 0.0.3__py3-none-any.whl → 0.20.1__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.
Files changed (37) hide show
  1. itkdb_gtk/{sendShipments.py → CreateShipments.py} +74 -78
  2. itkdb_gtk/{getShipments.py → GetShipments.py} +99 -106
  3. itkdb_gtk/GlueWeight.py +45 -66
  4. itkdb_gtk/ITkDB.desktop +8 -0
  5. itkdb_gtk/ITkDB.svg +380 -0
  6. itkdb_gtk/ITkDBlogin.py +10 -6
  7. itkdb_gtk/ITkDButils.py +295 -57
  8. itkdb_gtk/PanelVisualInspection.py +590 -0
  9. itkdb_gtk/QRScanner.py +120 -0
  10. itkdb_gtk/SensorUtils.py +492 -0
  11. itkdb_gtk/ShowAttachments.py +267 -0
  12. itkdb_gtk/ShowComments.py +94 -0
  13. itkdb_gtk/ShowDefects.py +103 -0
  14. itkdb_gtk/UploadModuleIV.py +566 -0
  15. itkdb_gtk/UploadMultipleTests.py +746 -0
  16. itkdb_gtk/UploadTest.py +509 -0
  17. itkdb_gtk/VisualInspection.py +297 -0
  18. itkdb_gtk/WireBondGui.py +1304 -0
  19. itkdb_gtk/__init__.py +38 -12
  20. itkdb_gtk/dashBoard.py +292 -33
  21. itkdb_gtk/dbGtkUtils.py +356 -75
  22. itkdb_gtk/findComponent.py +242 -0
  23. itkdb_gtk/findVTRx.py +36 -0
  24. itkdb_gtk/readGoogleSheet.py +1 -2
  25. itkdb_gtk/untrash_component.py +35 -0
  26. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/METADATA +21 -12
  27. itkdb_gtk-0.20.1.dist-info/RECORD +30 -0
  28. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/WHEEL +1 -1
  29. itkdb_gtk-0.20.1.dist-info/entry_points.txt +12 -0
  30. itkdb_gtk/checkComponent.py +0 -131
  31. itkdb_gtk/groundingTest.py +0 -225
  32. itkdb_gtk/readAVSdata.py +0 -565
  33. itkdb_gtk/uploadPetalInformation.py +0 -604
  34. itkdb_gtk/uploadTest.py +0 -384
  35. itkdb_gtk-0.0.3.dist-info/RECORD +0 -19
  36. itkdb_gtk-0.0.3.dist-info/entry_points.txt +0 -7
  37. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,566 @@
1
+ #!/usr/bin/env python3
2
+ """Read IV files and create plots.
3
+
4
+ Analisis de la IV con macros de la webApp
5
+
6
+ SENSOR_IV_Analysis.py in
7
+ https://gitlab.cern.ch/atlas-itk/sw/db/production_database_scripts.git
8
+
9
+ webApp aqui:
10
+ https://itk-pdb-webapps-strips.web.cern.ch
11
+
12
+ """
13
+ import sys
14
+ import os
15
+ import json
16
+ import tempfile
17
+ import copy
18
+ from pathlib import Path
19
+
20
+ from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas
21
+ from matplotlib.backends.backend_gtk3 import NavigationToolbar2GTK3 as NavigationToolbar
22
+ import numpy as np
23
+ import matplotlib as mpl
24
+ import matplotlib.pyplot as plt
25
+
26
+ import gi
27
+
28
+ gi.require_version("Gtk", "3.0")
29
+ from gi.repository import Gtk, Gio
30
+
31
+ try:
32
+ import itkdb_gtk
33
+
34
+ except ImportError:
35
+ cwd = Path(__file__).parent.parent
36
+ sys.path.append(cwd.as_posix())
37
+
38
+ from itkdb_gtk import dbGtkUtils, ITkDBlogin, ITkDButils, UploadTest, SensorUtils
39
+
40
+ # Check if Gtk can be open
41
+ gtk_runs, gtk_args = Gtk.init_check()
42
+
43
+
44
+ def remove_files(W, flist):
45
+ """Remove files given in the input list.
46
+
47
+ Args:
48
+ flist (list): list of filenames.
49
+
50
+ """
51
+ for f in flist:
52
+ os.unlink(f)
53
+
54
+
55
+ class IVwindow(dbGtkUtils.ITkDBWindow):
56
+ """GUI for IV file handling."""
57
+
58
+ def __init__(self, session, title="IV window", options=None, help_link=None):
59
+ """Initialization."""
60
+ super().__init__(session=session, title=title,
61
+ show_search=None, gtk_runs=gtk_runs,
62
+ help_link=help_link
63
+ )
64
+ self.mdata = {}
65
+ self.mod_type = {}
66
+ self.mod_SN = {}
67
+ self.last_folder = None
68
+ self.difference = None
69
+ self.canvas = None
70
+
71
+ self.init_window()
72
+
73
+ def init_window(self):
74
+ """Prepare the Gtk window."""
75
+ self.hb.props.title = "IV data"
76
+
77
+ button = Gtk.Button()
78
+ icon = Gio.ThemedIcon(name="view-refresh-symbolic")
79
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
80
+ button.add(image)
81
+ button.set_tooltip_text("Click to refresh canvas.")
82
+ button.connect("clicked", self.on_refresh)
83
+ self.hb.pack_end(button)
84
+
85
+ # Button to upload
86
+ button = Gtk.Button()
87
+ icon = Gio.ThemedIcon(name="document-send-symbolic")
88
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
89
+ button.add(image)
90
+ button.set_tooltip_text("Click to upload test")
91
+ button.connect("clicked", self.do_upload)
92
+ self.hb.pack_end(button)
93
+
94
+ # File entry and search button
95
+ self.single_file = Gtk.FileChooserButton()
96
+ self.single_file.connect("file-set", self.on_single_file_set)
97
+
98
+ self.double_file = Gtk.FileChooserButton()
99
+ self.double_file.connect("file-set", self.on_double_file_set)
100
+
101
+ self.single_SN = Gtk.Label(label="(None)")
102
+ self.double_SN = Gtk.Label(label="(None)")
103
+
104
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
105
+
106
+ grid.attach(Gtk.Label(label="Files"), 1, 0, 1, 1)
107
+ grid.attach(Gtk.Label(label="Serial No."), 2, 0, 1, 1)
108
+
109
+ grid.attach(Gtk.Label(label="Single Data File"), 0, 1, 1, 1)
110
+ grid.attach(self.single_file, 1, 1, 1, 1)
111
+ grid.attach(self.single_SN, 2, 1, 1, 1)
112
+
113
+ grid.attach(Gtk.Label(label="Double Data File"), 0, 2, 1, 1)
114
+ grid.attach(self.double_file, 1, 2, 1, 1)
115
+ grid.attach(self.double_SN, 2, 2, 1, 1)
116
+
117
+ #btn = Gtk.Button(label="Compute difference")
118
+ #btn.connect("clicked", self.on_difference)
119
+ #grid.attach(btn, 1, 3, 1, 1)
120
+
121
+ btn = Gtk.Button(label="Upload to DB")
122
+ btn.connect("clicked", self.do_upload)
123
+ grid.attach(btn, 2, 3, 1, 1)
124
+
125
+ self.mainBox.pack_start(grid, False, True, 0)
126
+
127
+ self.fig = mpl.figure.Figure()
128
+ self.fig.tight_layout()
129
+ sw = Gtk.ScrolledWindow() # Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
130
+
131
+ # A scrolled window border goes outside the scrollbars and viewport
132
+ sw.set_border_width(10)
133
+ sw.set_size_request(310, 310)
134
+
135
+ self.canvas = FigureCanvas(self.fig) # a Gtk.DrawingArea
136
+ self.canvas.set_size_request(400, 300)
137
+ sw.add(self.canvas)
138
+ self.mainBox.pack_start(sw, True, True, 0)
139
+
140
+ # Create toolbar
141
+ try:
142
+ toolbar = NavigationToolbar(self.canvas)
143
+ except TypeError:
144
+ toolbar = NavigationToolbar(self.canvas, self)
145
+
146
+ self.mainBox.pack_start(toolbar, False, False, 0)
147
+
148
+ # The text view
149
+ self.mainBox.pack_start(self.message_panel.frame, True, True, 5)
150
+
151
+ self.show_all()
152
+
153
+ def get_difference_data(self):
154
+ """Returns the double data witht the difference."""
155
+ # Prepare the data
156
+ ddata = copy.deepcopy(self.mdata["double"])
157
+
158
+ ndata = len(self.difference)
159
+ ddata["curve"]["V"] = np.abs(ddata["curve"]["V"][:ndata])
160
+ ddata["curve"]["I"] = np.abs(self.difference)
161
+ ddata["curve"]["S"] = ddata["curve"]["S"][:ndata]
162
+ return ddata
163
+
164
+ def upload_test(self, mdata, mod_type):
165
+ """Upload available tests."""
166
+
167
+ # Get JSon skeleton filled
168
+ test = SensorUtils.sensor_data_to_json(self.session, mdata, mod_type, self)
169
+
170
+ # write attachment.
171
+ # First geet the fine name.
172
+ fnam = SensorUtils.build_file_name(mdata)
173
+
174
+
175
+ data_out = tempfile.NamedTemporaryFile("w", prefix=fnam, suffix=".dat", delete=False)
176
+ SensorUtils.save_sensor_data(data_out, mdata, name=fnam)
177
+
178
+ js_out = tempfile.NamedTemporaryFile("w", prefix="payload-", suffix=".json", delete=False)
179
+ js_out.write(json.dumps(test, indent=3, cls=dbGtkUtils.MyEncoder))
180
+ js_out.close()
181
+
182
+ attachment = ITkDButils.Attachment(path=data_out.name, title="resultsFile", desc=fnam)
183
+ uploadW = UploadTest.UploadTest(self.session, js_out.name, attachment)
184
+ uploadW.connect("destroy", remove_files, [data_out.name, js_out.name])
185
+
186
+
187
+ def do_upload(self, *args):
188
+ """The upload button has been clicked.
189
+
190
+ We present a dialog where we ask if the new data file should be stored
191
+ locally and if both (single and difference) tests should be uploaded.
192
+ """
193
+ if "single" not in self.mdata:
194
+ return
195
+
196
+ if "double" not in self.mdata:
197
+ # upload only the single test.
198
+ if dbGtkUtils.ask_for_confirmation(
199
+ "Uploading Single data",
200
+ "No data for double module/sensor.\nUpload single test ?."):
201
+
202
+ self.upload_test(self.mdata["single"], self.mod_type["single"])
203
+
204
+ return
205
+
206
+ # We create the dialog.
207
+ dlg = Gtk.Dialog(title="Add Attachment", parent=self, flags=0)
208
+ dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
209
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
210
+ area = dlg.get_content_area()
211
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
212
+ area.add(grid)
213
+
214
+ label = Gtk.Label(label="Save locally new data file ?")
215
+ save_locally = Gtk.Switch()
216
+ grid.attach(label, 0, 0, 1, 1)
217
+ grid.attach(save_locally, 1, 0, 1, 1)
218
+
219
+ label = Gtk.Label(label="Upload both tests ?")
220
+ do_both = Gtk.Switch()
221
+ grid.attach(label, 0, 1, 1, 1)
222
+ grid.attach(do_both, 1, 1, 1, 1)
223
+
224
+ dlg.show_all()
225
+ rc = dlg.run()
226
+ dlg.hide()
227
+ if rc != Gtk.ResponseType.OK:
228
+ dlg.destroy()
229
+ return
230
+
231
+ mdata = self.get_difference_data()
232
+ if save_locally.get_active():
233
+ # Save locally.
234
+ fnam = SensorUtils.build_file_name(mdata)
235
+ fc = Gtk.FileChooserDialog(title="Save data file", action=Gtk.FileChooserAction.SAVE)
236
+ fc.add_buttons(
237
+ Gtk.STOCK_CANCEL,
238
+ Gtk.ResponseType.CANCEL,
239
+ Gtk.STOCK_OPEN,
240
+ Gtk.ResponseType.OK,
241
+ )
242
+
243
+ if self.last_folder:
244
+ fc.set_current_folder(self.last_folder)
245
+
246
+ fc.set_current_name("{}.dat".format(fnam))
247
+ rc = fc.run()
248
+ if rc == Gtk.ResponseType.OK:
249
+ SensorUtils.save_sensor_data(fc.get_filename(), mdata)
250
+
251
+ fc.hide()
252
+ fc.destroy()
253
+
254
+ # Upload double
255
+ self.upload_test(mdata, self.mod_type["double"])
256
+
257
+ if do_both.get_active():
258
+ self.upload_test(self.mdata["single"], self.mod_type["single"])
259
+
260
+ dlg.destroy()
261
+
262
+ def on_refresh(self, *args):
263
+ """Refresh canvas."""
264
+ if self.fig and self.canvas:
265
+ self.fig.tight_layout()
266
+ self.canvas.draw()
267
+
268
+ def find_module(self, SN):
269
+ """Find module (SN) on database
270
+
271
+ Args:
272
+ SN (str): Module Serial number.
273
+
274
+ """
275
+ md = ITkDButils.get_DB_component(self.session, SN)
276
+ if md is None:
277
+ dbGtkUtils.complain(
278
+ "Could not find {}".format(SN), str(ITkDButils.get_db_response())
279
+ )
280
+
281
+ return md
282
+
283
+ def update_folder(self, fnam):
284
+ """Sets last folder."""
285
+
286
+ self.last_folder = Path(fnam).parent.as_posix()
287
+ self.single_file.set_current_folder(self.last_folder)
288
+ self.double_file.set_current_folder(self.last_folder)
289
+
290
+ def show_single_curve(self):
291
+ """Shows the single curve."""
292
+ try:
293
+ mdata = self.mdata["single"]
294
+ except KeyError:
295
+ return
296
+
297
+ is_module = is_module = "Module_SN" in mdata
298
+
299
+ self.show_curve(
300
+ 131,
301
+ mdata["curve"]["V"],
302
+ mdata["curve"]["I"],
303
+ self.mod_type["single"][0:4] if is_module else "Single",
304
+ mdata["curve"]["labels"][0],
305
+ mdata["curve"]["labels"][1],
306
+ )
307
+
308
+ def show_double_curve(self):
309
+ """Shows the double curve."""
310
+ try:
311
+ mdata = self.mdata["double"]
312
+ except KeyError:
313
+ return
314
+
315
+ self.show_curve(
316
+ 133,
317
+ mdata["curve"]["V"],
318
+ mdata["curve"]["I"],
319
+ "Double",
320
+ mdata["curve"]["labels"][0],
321
+ None,
322
+ )
323
+
324
+ def on_single_file_set(self, *args):
325
+ """Single sensor file chosen."""
326
+ obj_type = ["sensor", "module"]
327
+ fnam = self.single_file.get_filename()
328
+ if fnam is None or not Path(fnam).exists():
329
+ dbGtkUtils.complain("Could not find data file", fnam, parent=self)
330
+
331
+ mdata = SensorUtils.read_sensor_file(fnam)
332
+ self.update_folder(fnam)
333
+
334
+ is_module = 1
335
+ try:
336
+ SN = mdata["Module_SN"]
337
+
338
+ except KeyError:
339
+ SN = mdata["Component"]
340
+ is_module = 0
341
+
342
+ self.write_message("Reading data for {} {}\n".format(obj_type[is_module], SN))
343
+ md = self.find_module(SN)
344
+ if md is None:
345
+ self.write_message("...object does not exist.\n")
346
+ self.single_file.unselect_all()
347
+ return
348
+
349
+ # All good
350
+ self.mod_SN["single"] = SN
351
+ self.mdata["single"] = mdata
352
+ self.mod_type["single"] = md["type"]["code"]
353
+ print(self.mod_type["single"])
354
+
355
+ self.single_SN.set_text("{} - {}".format(SN, md["type"]["name"]))
356
+ self.fig.clf()
357
+ self.show_single_curve()
358
+
359
+ # Compute difference if single already available
360
+ if "double" in self.mdata:
361
+ self.show_double_curve()
362
+ self.on_difference()
363
+
364
+ def check_double_SN(self, SN, is_module):
365
+ """Check that the double SN is a good one."""
366
+ obj_type = ["sensor", "module"]
367
+ if "single" in self.mod_SN:
368
+ if self.mod_SN["single"] == SN:
369
+ dbGtkUtils.complain(
370
+ "Wrong SN {}".format(SN),
371
+ "{} already used.".format(obj_type[is_module])
372
+ )
373
+ self.double_file.unselect_all()
374
+ return None
375
+
376
+ # Check that it exists in the DB
377
+ if len(SN) != 14 or SN[0:4] != "20US":
378
+ self.write_message("Invalid SN: {}\n".format(SN))
379
+ SN = dbGtkUtils.get_a_value(
380
+ "Invalid SN", "Give Ring or corresponding Half Module SN"
381
+ )
382
+ return None
383
+
384
+ md = self.find_module(SN)
385
+ if md is None:
386
+ self.write_message("...object does not exist.\n")
387
+ self.double_file.unselect_all()
388
+ return None
389
+
390
+ return md
391
+
392
+ def get_true_SN(self, md):
393
+ """Get the actual SN of the 'double' object."""
394
+ found_child = False
395
+ has_ring = md["type"]["name"].find("Ring")
396
+ if has_ring >= 0:
397
+ self.write_message("...This is a Ring module. Searching children in DB\n")
398
+ for child in md["children"]:
399
+ if child["component"]:
400
+ ctype = child["type"]["code"]
401
+ if ctype.find("MODULE") < 0:
402
+ continue
403
+
404
+ cSN = child["component"]["serialNumber"]
405
+ if cSN == self.mod_SN["single"]:
406
+ continue
407
+
408
+ halfM_SN = cSN
409
+ found_child = True
410
+ self.write_message("...found {}\n".format(halfM_SN))
411
+ break
412
+
413
+ if not found_child:
414
+ self.write_message("Requesting a Half Module SN\n")
415
+ halfM_SN = dbGtkUtils.get_a_value(
416
+ "Give Half Module SN", "Serial Number"
417
+ )
418
+
419
+ md = ITkDButils.get_DB_component(self.session, halfM_SN)
420
+ if md is None:
421
+ dbGtkUtils.complain(
422
+ "Could not find {}".format(halfM_SN),
423
+ str(ITkDButils.get_db_response()),
424
+ )
425
+ self.double_file.unselect_all()
426
+ return None
427
+
428
+ self.write_message("... {}\n".format(halfM_SN))
429
+ return halfM_SN
430
+
431
+ return md["serialNumber"]
432
+
433
+ def on_double_file_set(self, *args):
434
+ "File chosen for the 'double module'"
435
+ obj_type = ["sensor", "module"]
436
+ fnam = self.double_file.get_filename()
437
+ if fnam is None or not Path(fnam).exists():
438
+ dbGtkUtils.complain("Could not find data file", fnam, parent=self)
439
+
440
+ mdata = SensorUtils.read_sensor_file(fnam)
441
+ self.update_folder(fnam)
442
+ is_module = 1
443
+ # Check SN in data file
444
+ try:
445
+ SN = mdata["Module_SN"]
446
+ except KeyError:
447
+ is_module = 0
448
+ SN = mdata["Component"]
449
+
450
+ halfM_SN = SN
451
+ md = self.check_double_SN(SN, is_module)
452
+ if md is None:
453
+ return
454
+
455
+ self.write_message("Reading data for {} {}\n".format(obj_type[is_module], SN))
456
+ halfM_SN = self.get_true_SN(md)
457
+ if halfM_SN is None:
458
+ return
459
+
460
+ if "single" in self.mod_type:
461
+ if is_module and self.mod_type["single"] == md["type"]["code"]:
462
+ dbGtkUtils.complain(
463
+ "Wrong module type.",
464
+ "Module type cannot be {}".format(self.mod_type["single"]),
465
+ )
466
+
467
+ self.double_file.unselect_all()
468
+ return
469
+
470
+ self.mod_SN["double"] = halfM_SN
471
+ self.mod_type["double"] = md["type"]["code"]
472
+ self.mdata["double"] = mdata
473
+
474
+ self.double_SN.set_text("{} - {}".format(halfM_SN, md["type"]["name"]))
475
+ self.show_double_curve()
476
+
477
+ # Compute difference if single already available
478
+ if "single" in self.mdata:
479
+ self.on_difference()
480
+
481
+ def on_difference(self, *args):
482
+ """Compute difference."""
483
+ if "single" not in self.mdata or "double" not in self.mdata:
484
+ dbGtkUtils.complain(
485
+ "Data needed", "Check if single oand doubel module data are available"
486
+ )
487
+ return
488
+
489
+ is_module = "Module_SN" in self.mdata["double"]
490
+ double_I = self.mdata["double"]["curve"]["I"]
491
+ single_I = SensorUtils.scale_iv(
492
+ self.mdata["single"]["curve"]["I"],
493
+ self.mdata["single"]["Temperature"] + 273.0,
494
+ self.mdata["double"]["Temperature"] + 273.0,
495
+ )
496
+
497
+ try:
498
+ nmin = double_I.size
499
+ self.difference = double_I - single_I
500
+ except ValueError:
501
+ nmin = np.min([double_I.size, single_I.size])
502
+ self.write_message(
503
+ "Size of current arrays is not the same: {} {}\n".format(
504
+ double_I.size, single_I.size
505
+ )
506
+ )
507
+ self.difference = double_I[:nmin] - single_I[:nmin]
508
+
509
+ self.show_curve(
510
+ 132,
511
+ self.mdata["double"]["curve"]["V"][:nmin],
512
+ self.difference,
513
+ self.mod_type["double"][0:4] if is_module else "Diff",
514
+ self.mdata["double"]["curve"]["labels"][0],
515
+ None,
516
+ )
517
+
518
+ def show_curve(self, subplot, X, Y, title=None, xlabel="X", ylabel="Y"):
519
+ """Shows data"""
520
+ ax = self.fig.add_subplot(subplot)
521
+ plt.cla()
522
+ if xlabel:
523
+ ax.set_xlabel(xlabel)
524
+
525
+ if ylabel:
526
+ ax.set_ylabel(ylabel)
527
+
528
+ if title:
529
+ ax.set_title(title)
530
+
531
+ ax.plot(X, Y)
532
+ ax.grid()
533
+ self.on_refresh()
534
+
535
+
536
+ def main():
537
+ """Main entryy."""
538
+
539
+ # DB login
540
+ dlg = ITkDBlogin.ITkDBlogin()
541
+ client = dlg.get_client()
542
+ if client is None:
543
+ print("Could not connect to DB with provided credentials.")
544
+ dlg.die()
545
+ sys.exit()
546
+
547
+ client.user_gui = dlg
548
+
549
+ # Start the Application
550
+ win = IVwindow(client)
551
+ win.show_all()
552
+ win.set_accept_focus(True)
553
+ win.present()
554
+ win.connect("destroy", Gtk.main_quit)
555
+
556
+ try:
557
+ Gtk.main()
558
+ except KeyboardInterrupt:
559
+ print("Arrggggg !!!")
560
+
561
+ dlg.die()
562
+ print("Bye !!")
563
+ sys.exit()
564
+
565
+ if __name__ == "__main__":
566
+ main()