petal-qc 0.0.14.dev1__tar.gz → 0.0.16__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 petal-qc might be problematic. Click here for more details.

Files changed (83) hide show
  1. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/PKG-INFO +1 -1
  2. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/__init__.py +12 -2
  3. {petal_qc-0.0.14.dev1/petal_qc/test → petal_qc-0.0.16/petal_qc}/getPetalCoreTestSummary.py +41 -6
  4. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/PetalMetrology.py +0 -13
  5. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/analyze_locking_points.py +4 -4
  6. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/compare_Cores.py +69 -4
  7. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/coreMetrology.py +0 -12
  8. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/do_Metrology.py +30 -16
  9. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/petal_flatness.py +0 -13
  10. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/readAVSdata.py +2 -0
  11. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/uploadPetalInformation.py +17 -17
  12. petal_qc-0.0.16/petal_qc/test/analyzeMetrologyTable.py +119 -0
  13. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/checkAVStests.py +2 -2
  14. petal_qc-0.0.16/petal_qc/test/createMetrologyFile.py +77 -0
  15. petal_qc-0.0.16/petal_qc/test/createMetrologyTable.py +87 -0
  16. petal_qc-0.0.16/petal_qc/test/desyModuleBow.py +126 -0
  17. petal_qc-0.0.16/petal_qc/test/findRawData.py +92 -0
  18. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/getAVStests.py +8 -0
  19. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/prepareDESYfiles.py +13 -2
  20. petal_qc-0.0.16/petal_qc/test/reportFromJSon.py +51 -0
  21. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/show_IR_petal.py +1 -10
  22. petal_qc-0.0.16/petal_qc/utils/ArgParserUtils.py +41 -0
  23. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/PKG-INFO +1 -1
  24. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/SOURCES.txt +8 -1
  25. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/entry_points.txt +2 -0
  26. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/pyproject.toml +3 -1
  27. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/README.md +0 -0
  28. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/BTreport/CheckBTtests.py +0 -0
  29. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/BTreport/__init__.py +0 -0
  30. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/BTreport/bustapeReport.py +0 -0
  31. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/PetalReceptionTests.py +0 -0
  32. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/dashBoard.py +0 -0
  33. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/Cluster.py +0 -0
  34. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/DataFile.py +0 -0
  35. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/__init__.py +0 -0
  36. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/all2csv.py +0 -0
  37. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/cold_noise.py +0 -0
  38. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/comparisonTable.py +0 -0
  39. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/convert_mitutoyo.py +0 -0
  40. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/convert_smartscope.py +0 -0
  41. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/data2csv.py +0 -0
  42. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/flatness4nigel.py +0 -0
  43. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/gtkutils.py +0 -0
  44. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/show_data_file.py +0 -0
  45. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/testSummary.py +0 -0
  46. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/metrology/test_paralelism.py +0 -0
  47. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/compare_golden.py +0 -0
  48. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/getAVSjson.py +0 -0
  49. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/listPetalCoreComponents.py +0 -0
  50. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/test_Graphana.py +0 -0
  51. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/test/test_coreThermal.py +0 -0
  52. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/CSVImage.py +0 -0
  53. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/DESYdata.py +0 -0
  54. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/DebugPlot.py +0 -0
  55. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/IRBFile.py +0 -0
  56. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/IRCore.py +0 -0
  57. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/IRDataGetter.py +0 -0
  58. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/IRPetal.py +0 -0
  59. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/IRPetalParam.py +0 -0
  60. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/PetalColorMaps.py +0 -0
  61. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/Petal_IR_Analysis.py +0 -0
  62. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/PipeFit.py +0 -0
  63. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/__init__.py +0 -0
  64. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/analyze_IRCore.py +0 -0
  65. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/contours.py +0 -0
  66. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/coreThermal.py +0 -0
  67. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/create_IRCore.py +0 -0
  68. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/create_core_report.py +0 -0
  69. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/pipe_back.npz +0 -0
  70. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/pipe_front.npz +0 -0
  71. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/thermal/pipe_read.py +0 -0
  72. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/Geometry.py +0 -0
  73. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/Progress.py +0 -0
  74. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/__init__.py +0 -0
  75. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/all_files.py +0 -0
  76. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/docx_utils.py +0 -0
  77. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/fit_utils.py +0 -0
  78. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/readGraphana.py +0 -0
  79. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc/utils/utils.py +0 -0
  80. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/dependency_links.txt +0 -0
  81. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/requires.txt +0 -0
  82. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/petal_qc.egg-info/top_level.txt +0 -0
  83. {petal_qc-0.0.14.dev1 → petal_qc-0.0.16}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: petal_qc
3
- Version: 0.0.14.dev1
3
+ Version: 0.0.16
4
4
  Summary: A collection of scripts for Petal CORE QC.
5
5
  Author-email: Carlos Lacasta <carlos.lacasta@cern.ch>
6
6
  Project-URL: Homepage, https://gitlab.cern.ch/atlas-itk/sw/db/itk-pdb-gtk-gui-utils
@@ -1,5 +1,5 @@
1
1
  """petal_qc python module."""
2
- __version__ = "0.0.14.dev1"
2
+ __version__ = "0.0.16"
3
3
 
4
4
 
5
5
  def coreMetrology():
@@ -9,9 +9,14 @@ def coreMetrology():
9
9
 
10
10
  def doMetrology():
11
11
  """Launches the Core metrology analysis in the command line."""
12
- from .metrology.do_metrology import main
12
+ from .metrology.do_Metrology import main
13
13
  main()
14
14
 
15
+ def coreMetrologyTTY():
16
+ """Launches the Core metrology analysis in the command line."""
17
+ from .metrology.do_Metrology import analyze_core_metrology
18
+ analyze_core_metrology()
19
+
15
20
  def coreThermal():
16
21
  """Launches the Core thermal analysis ahd PDB script."""
17
22
  from .thermal.coreThermal import main
@@ -43,6 +48,11 @@ def petalReceptionTests():
43
48
  from .PetalReceptionTests import main
44
49
  main()
45
50
 
51
+ def petalCoreTestSummary():
52
+ """GND/VI tests."""
53
+ from .getPetalCoreTestSummary import main
54
+ main()
55
+
46
56
  def dashBoard():
47
57
  """Launches the Core thermal analysis ahd PDB script."""
48
58
  from .dashBoard import main
@@ -1,20 +1,26 @@
1
1
  #!/usr/bin/env python3
2
2
  """Get a summery of Petal core TEsts."""
3
+ import json
4
+ import sys
5
+ import re
6
+ from argparse import ArgumentParser
3
7
 
8
+
9
+ from pathlib import Path
4
10
  try:
5
11
  import itkdb_gtk
6
12
 
7
13
  except ImportError:
8
- import sys
9
- from pathlib import Path
10
14
  cwd = Path(__file__).parent.parent
11
15
  sys.path.append(cwd.as_posix())
12
16
 
13
17
  from itkdb_gtk import ITkDBlogin, ITkDButils
14
18
  from itkdb_gtk.dbGtkUtils import replace_in_container, DictDialog, ask_for_confirmation
19
+ from petal_qc.utils.ArgParserUtils import RangeListAction
15
20
 
21
+ r_petal_id = re.compile("PPC.([0-9]*)")
16
22
 
17
- def main(session):
23
+ def petalCoreTest(session, options):
18
24
  """Main entry point."""
19
25
 
20
26
  # find all cores
@@ -24,17 +30,25 @@ def main(session):
24
30
  #"componentType": ["BT"],
25
31
  "componentType": ["CORE_PETAL"],
26
32
  "type": ["CORE_AVS"],
27
- "currentLocation": ["IFIC"],
33
+ # "currentLocation": ["IFIC"],
28
34
  },
29
35
  "sorterList": [
30
36
  {"key": "alternativeIdentifier", "descending": False }
31
37
  ],
32
38
  }
39
+ suff = "ALL"
40
+ if options.institute:
41
+ payload["filterMap"]["currentLocation"] = options.institute
42
+ suff = options.institute
43
+
33
44
  core_list = session.get("listComponents", json=payload)
34
45
  core_tests = ["PETAL_METROLOGY_FRONT", "PETAL_METROLOGY_BACK", "XRAYIMAGING", "THERMAL_EVALUATION", "BTTESTING"]
35
46
 
36
47
  do_check_stage = "AT_QC_SITE"
37
48
  #do_check_stage = None
49
+ petal_id_db = {}
50
+
51
+ has_list = len(options.cores) != 0
38
52
 
39
53
  for core in core_list:
40
54
  SN = core["serialNumber"]
@@ -42,7 +56,16 @@ def main(session):
42
56
  if "PPC" not in altid:
43
57
  continue
44
58
 
59
+ R = r_petal_id.search(altid)
60
+ if R is None:
61
+ continue
45
62
 
63
+ pid = int(R.group(1))
64
+
65
+ if has_list and pid not in options.cores:
66
+ continue
67
+
68
+ petal_id_db[altid] = SN
46
69
  location = core["currentLocation"]['code']
47
70
  coreStage = core["currentStage"]['code']
48
71
  if do_check_stage:
@@ -73,17 +96,29 @@ def main(session):
73
96
  for D in T["defects"]:
74
97
  print("\t{} - {}".format(D["name"], D["description"]))
75
98
 
99
+ with open("petal_ID_db_{}.json".format(suff), "w", encoding="utf-8") as fOut:
100
+ json.dump(petal_id_db, fOut, indent=3)
76
101
 
77
- if __name__ == "__main__":
102
+ def main():
103
+ """Main entry"""
104
+ parser = ArgumentParser()
105
+ parser.add_argument("--institute", default=None, help="The petal current location")
106
+ parser.add_argument("--cores", dest="cores", action=RangeListAction, default=[],
107
+ help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
108
+ options = parser.parse_args()
109
+
78
110
  # ITk_PB authentication
79
111
  dlg = ITkDBlogin.ITkDBlogin()
80
112
  session = dlg.get_client()
81
113
 
82
114
  try:
83
- main(session)
115
+ petalCoreTest(session, options)
84
116
 
85
117
  except Exception as E:
86
118
  print(E)
87
119
 
88
120
  dlg.die()
121
+
122
+ if __name__ == "__main__":
123
+ main()
89
124
 
@@ -45,19 +45,6 @@ def check_spec(val, nom, fraction=0.0):
45
45
  rc = val <= (1+fraction)*nom
46
46
  return rc
47
47
 
48
-
49
- class CommaSeparatedListAction(Action):
50
- """Create a list from the comma sepparated numbers at imput."""
51
-
52
- def __call__(self, args_parser, namespace, values, option_string=None):
53
- """The actual action."""
54
- value = np.array(list(map(float, values.split(','))), dtype='float64')
55
- if value.shape[0] < 3:
56
- raise ValueError("{} needs a 3D vector".format(self.dest))
57
-
58
- setattr(namespace, self.dest, value)
59
-
60
-
61
48
  def petal_metrology(ifile, options):
62
49
  """Do the analysis of the petal metrology data.
63
50
 
@@ -513,12 +513,12 @@ def locking_point_positions(positions, document=None):
513
513
  dPL2 = np.linalg.norm(positions[1, 0:2] - positions[4, 0:2])
514
514
  deltaPL1 = (nPL1-dPL1)
515
515
  deltaPL2 = (nPL2-dPL2)
516
- fPL1 = "PASSED" if abs(deltaPL1) <= 0.050 else "FAILED"
517
- fPL2 = "PASSED" if abs(deltaPL2) <= 0.050 else "FAILED"
516
+ fPL1 = "PASSED" if abs(deltaPL1) <= 0.075 else "FAILED"
517
+ fPL2 = "PASSED" if abs(deltaPL2) <= 0.075 else "FAILED"
518
518
 
519
519
  for key, val in outDB["REL_POS_DELTA"].items():
520
520
  deltaPL = np.linalg.norm(val)
521
- fPL = "PASSED" if abs(deltaPL) <= 0.050 else "FAILED"
521
+ fPL = "PASSED" if abs(deltaPL) <= 0.075 else "FAILED"
522
522
  print("Distance {}: {:.3f} mm ({})".format(key, deltaPL, fPL))
523
523
 
524
524
  if document:
@@ -559,7 +559,7 @@ def locking_point_positions(positions, document=None):
559
559
  document.add_paragraph("")
560
560
  for key, val in outDB["REL_POS_DELTA"].items():
561
561
  deltaPL = np.linalg.norm(val)
562
- fPL = "PASSED" if abs(deltaPL) <= 0.050 else "FAILED"
562
+ fPL = "PASSED" if abs(deltaPL) <= 0.075 else "FAILED"
563
563
  document.add_paragraph("Distance {}: {:.3f} mm ({})".format(key, deltaPL, fPL))
564
564
 
565
565
  return outDB
@@ -2,13 +2,43 @@
2
2
  """Compare quantities."""
3
3
 
4
4
  import sys
5
+ import re
6
+
5
7
  import argparse
6
8
  import glob
7
9
  import json
10
+ import math
8
11
  from pathlib import Path
9
12
  import numpy as np
10
13
  import matplotlib.pyplot as plt
11
14
 
15
+ r_petal_id = re.compile("PPC.([0-9]*)")
16
+
17
+ class PetalCoreListAction(argparse.Action):
18
+ """Create a list from the comma sepparated numbers at imput."""
19
+
20
+ def __call__(self, parser, namespace, values, option_string=None):
21
+ """The actual action."""
22
+ value = []
23
+ for V in values.split(','):
24
+ try:
25
+ value.append(int(V))
26
+ except ValueError:
27
+ if ':' not in V:
28
+ continue
29
+
30
+ items = V.split(':')
31
+ if len(items)==1:
32
+ continue
33
+
34
+ ival = list(map(int, items))
35
+ ival[1] += 1
36
+ for x in range(*ival):
37
+ value.append(int(x))
38
+
39
+
40
+ setattr(namespace, self.dest, value)
41
+
12
42
 
13
43
  def get_value(data, value_path):
14
44
  """Get the value from the path given."""
@@ -58,12 +88,25 @@ def read_data_files(options):
58
88
  front = {}
59
89
  back = {}
60
90
 
91
+ has_list = len(options.cores) != 0
92
+
61
93
  for fnam in options.files:
62
94
  ifile = Path(fnam).expanduser().resolve()
63
95
  if not ifile.exists():
64
96
  print("File does not exist: ", fnam)
65
97
  continue
66
98
 
99
+ R = r_petal_id.search(fnam)
100
+ if R is None:
101
+ continue
102
+
103
+ petal_id = R.group(0)
104
+ pid = int(R.group(1))
105
+
106
+ if has_list and pid not in options.cores:
107
+ continue
108
+
109
+
67
110
  data = None
68
111
  with open(ifile, 'r', encoding="UTF-8") as fp:
69
112
  data = json.load(fp)
@@ -100,17 +143,22 @@ def draw_deltas(data, keys, fnam=None, title="Front", draw_text=True):
100
143
  P = [np.zeros([nfiles, 2]),
101
144
  np.zeros([nfiles, 2]),
102
145
  np.zeros([nfiles, 2])]
146
+ D = [[],[],[]]
147
+
103
148
  fig_width = 12.0
104
149
  fig_height = 1.2*fig_width/3.0
105
150
  fig, ax = plt.subplots(nrows=1, ncols=3, tight_layout=True, figsize=(fig_width, fig_height))
106
151
  fig.suptitle(title)
152
+ figb, bx = plt.subplots(nrows=1, ncols=3, tight_layout=True, figsize=(fig_width, fig_height))
153
+ figb.suptitle(title)
154
+
107
155
  for i in range(3):
108
156
  LBL = [[],[],[]]
109
157
  ax[i].set_title(keys[i])
110
158
  ax[i].set_aspect('equal', adjustable='box')
111
- ax[i].set_xlim(-100, 100)
112
- ax[i].set_ylim(-100, 100)
113
- circle = plt.Circle((0,0), 50, color="red", alpha=0.25)
159
+ ax[i].set_xlim(-150, 150)
160
+ ax[i].set_ylim(-150, 150)
161
+ circle = plt.Circle((0,0), 75, color="red", alpha=0.25)
114
162
  ax[i].add_patch(circle)
115
163
  circle = plt.Circle((0,0), 25, color="green", alpha=0.25)
116
164
  ax[i].add_patch(circle)
@@ -118,20 +166,34 @@ def draw_deltas(data, keys, fnam=None, title="Front", draw_text=True):
118
166
  ax[i].set_xlabel("X (µm)")
119
167
  ax[i].set_ylabel("Y (µm)")
120
168
  ax[i].grid()
169
+
170
+ bx[i].set_title(keys[i])
171
+ bx[i].set_xlabel("Distance (µm)")
172
+ bx[i].grid()
173
+
121
174
 
122
175
  for j, v in enumerate(data.items()):
123
176
  label, values = v
124
177
  for k in range(3):
125
178
  ky = key_table[keys[k]]
126
- P[k][j, :] = 1000*np.array(values[ky])
179
+ point = 1000*np.array(values[ky])
180
+ P[k][j, :] = point
181
+ D[k].append(math.sqrt(point[0]**2+point[1]**2))
127
182
  LBL[k].append(label.split('.')[1].lstrip('0'))
128
183
 
184
+ bx[i].hist(D[i], bins=15, range=(0, 150))
129
185
  ax[i].scatter(P[i][:,0], P[i][:,1])
130
186
  if draw_text:
131
187
  for j in range(len(LBL[i])):
132
188
  ax[i].text(P[i][j,0], P[i][j,1], LBL[i][j]) #, ha='center', va='top')
133
189
 
190
+ ofile = Path(fnam).expanduser().resolve()
191
+ print("* parent: ", ofile.parent)
192
+ print("* stem: ", ofile.stem)
193
+ bnam = ofile.parent / "{}-h.png".format(ofile.stem)
194
+ print(bnam.as_posix())
134
195
  save_figure(fig, fnam, prefix=title)
196
+ save_figure(figb, bnam, prefix=title)
135
197
 
136
198
 
137
199
  def show_positions(options):
@@ -184,6 +246,7 @@ def show_flatness(options):
184
246
  a.set_ylim(0, 1.2*max(y_lim[0][1], y_lim[1][1]))
185
247
  x_lim = a.get_xlim()
186
248
  a.fill_between(x_lim, 0, 0.050, facecolor="darkseagreen", alpha=0.1)
249
+ a.fill_between(x_lim, 0.050, 0.100, facecolor="mediumseagreen", alpha=0.1)
187
250
  if not options.no_legend:
188
251
  a.legend(ncol=3, fontsize="x-small")
189
252
 
@@ -230,6 +293,8 @@ if __name__ == "__main__":
230
293
  parser.add_argument("--out", default=None, help="File to store the figure.")
231
294
  parser.add_argument("--no-legend", dest="no_legend", default=False, action="store_true", help="Do not draw the legend")
232
295
  parser.add_argument("--no-show", dest="no_show", default=False, action="store_true", help="Do not show the figure")
296
+ parser.add_argument("--cores", dest="cores", action=PetalCoreListAction, default=[],
297
+ help="Create list of cores to analyze. The list is made with numbers or ranges (ch1:ch2 or ch1:ch2:step) ")
233
298
 
234
299
  opts = parser.parse_args()
235
300
  if len(opts.files) == 0:
@@ -18,18 +18,6 @@ from gi.repository import Gtk, GObject, Gio, GLib
18
18
 
19
19
  __HELP__ = "https://petal-qc.docs.cern.ch/metrology.html"
20
20
 
21
- class CommaSeparatedListAction(Action):
22
- """Create a list from the comma sepparated numbers at imput."""
23
-
24
- def __call__(self, parser, namespace, values, option_string=None):
25
- """The actual action."""
26
- value = np.array(list(map(float, values.split(','))), dtype='float64')
27
- if value.shape[0] < 3:
28
- raise ValueError("{} needs a 3D vector".format(self.dest))
29
-
30
- setattr(namespace, self.dest, value)
31
-
32
-
33
21
  class CoreMetrology(itkdb_gtk.dbGtkUtils.ITkDBWindow):
34
22
  """Application window."""
35
23
 
@@ -23,21 +23,8 @@ except ImportError:
23
23
  sys.path.append(cwd.as_posix())
24
24
 
25
25
  from petal_qc.utils.utils import output_folder
26
-
27
26
  from petal_qc.metrology.PetalMetrology import petal_metrology
28
27
 
29
-
30
- class CommaSeparatedListAction(Action):
31
- """Create a list from the comma sepparated numbers at imput."""
32
-
33
- def __call__(self, parser, namespace, values, option_string=None):
34
- """The actual action."""
35
- value = np.array(list(map(float, values.split(','))), dtype='float64')
36
- if value.shape[0] < 3:
37
- raise Exception("{} needs a 3D vector".format(self.dest))
38
-
39
- setattr(namespace, self.dest, value)
40
-
41
28
  def do_analysis(fnam, prefix, SN, options):
42
29
  """Perform analysis of a file.
43
30
 
@@ -68,6 +55,7 @@ def do_analysis(fnam, prefix, SN, options):
68
55
 
69
56
  def analyze_files(ifile, options):
70
57
  """Main entry."""
58
+ failed_files = []
71
59
  with open(ifile, 'r', encoding='UTF-8') as inp:
72
60
 
73
61
  for line in inp:
@@ -84,10 +72,26 @@ def analyze_files(ifile, options):
84
72
  except Exception:
85
73
  fnam, prefix, SN, *_ = line.split()
86
74
 
87
- do_analysis(fnam, prefix, SN, options)
75
+ try:
76
+ with open(fnam, "r", encoding="ISO-8859-1") as fin:
77
+ ss = fin.read()
78
+ if ss.find("Punto:")<0:
79
+ options.desy=True
80
+ else:
81
+ options.desy=False
82
+
83
+ do_analysis(fnam, prefix, SN, options)
84
+ print("\n\n")
85
+ except Exception as E:
86
+ failed_files.append([fnam, E])
87
+ continue
88
+
89
+ if len(failed_files)>0:
90
+ for fnam, E in failed_files:
91
+ print("### Failed file {}\n{}".format(fnam, E))
88
92
 
89
- def main():
90
- "Main entry."
93
+ def parse_options():
94
+ """Parse command line options."""
91
95
  parser = ArgumentParser()
92
96
  parser.add_argument('files', nargs='*', help="Input files")
93
97
  parser.add_argument("--prefix", dest='prefix', default=None, help="prefix telling if it is front or back.")
@@ -113,11 +117,21 @@ def main():
113
117
  print("I need an input file")
114
118
  sys.exit()
115
119
 
120
+ return options
121
+
122
+ def main():
123
+ "Main entry."
124
+ options = parse_options()
116
125
  try:
117
126
  analyze_files(options.files[0], options)
118
127
 
119
128
  except Exception:
120
129
  print(traceback.format_exc())
121
130
 
131
+ def analyze_core_metrology():
132
+ """Do a single file analysis."""
133
+ options = parse_options()
134
+ do_analysis(options.files[0], options.prefix, options.SN, options)
135
+
122
136
  if __name__ == "__main__":
123
137
  main()
@@ -31,19 +31,6 @@ from .show_data_file import show_data, TOP_VIEW
31
31
 
32
32
  figure_width = 14
33
33
 
34
-
35
- class CommaSeparatedListAction(Action):
36
- """Create a list from the comma sepparated numbers at imput."""
37
-
38
- def __call__(self, parser, namespace, values, option_string=None):
39
- """The actual action."""
40
- value = np.array(list(map(float, values.split(','))), dtype='float64')
41
- if value.shape[0] < 3:
42
- raise Exception("{} needs a 3D vector".format(self.dest))
43
-
44
- setattr(namespace, self.dest, value)
45
-
46
-
47
34
  def plot_sensor(Spoints, ax, marker='o', cmap='magma'):
48
35
  """Plot the points given in a scatter plot."""
49
36
  ax.scatter(Spoints[:, 0], Spoints[:, 1], Spoints[:, 2],
@@ -696,6 +696,8 @@ def readProductionSheet(session, file_path, SN):
696
696
  manufacturing["results"]["LOCATOR_B"] = sheet["{}{}".format(id_col, i_items+3)].value
697
697
  manufacturing["results"]["LOCATOR_C"] = sheet["{}{}".format(id_col, i_items+4)].value
698
698
  manufacturing["results"]["HONEYCOMBSET"] = split_comp_list( sheet["{}{}".format(id_col, i_items+5)].value)
699
+ manufacturing["results"]["HONEYCOMBSET"] = [ str(x) for x in manufacturing["results"]["HONEYCOMBSET"]]
700
+
699
701
  manufacturing["results"]["EPOXY_ADHESIVE"] = split_comp_list(sheet["{}{}".format(id_col, i_items+8)].value)
700
702
  manufacturing["results"]["EPOXY_PUTTY"] = split_comp_list( sheet["{}{}".format(id_col, i_items+9)].value)
701
703
  manufacturing["results"]["EPOXY_CONDUCTIVE"] = split_comp_list( sheet["{}{}".format(id_col, i_items+10)].value)
@@ -537,6 +537,23 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
537
537
  if self.petal_core is None:
538
538
  return
539
539
 
540
+ this_petal = self.SN.get_text()
541
+ # Check for HonneyComb set
542
+ for P in self.petal_core["properties"]:
543
+ if P["code"] == "HC_ID" and P["value"] is None:
544
+ if dbGtkUtils.is_iterable(components["HoneyCombSet"]):
545
+ val = ','.join([str(x) for x in components["HoneyCombSet"]])
546
+ else:
547
+ val = str(components["HoneyCombSet"])
548
+ rc = ITkDButils.set_component_property(self.session,
549
+ this_petal,
550
+ "HC_ID",
551
+ val)
552
+ if rc is None:
553
+ error_txt.append("Problems setting HoneyCombSet ID.\n")
554
+
555
+ break
556
+
540
557
  comp_map = {
541
558
  "BT_PETAL_FRONT": "FacingFront",
542
559
  "BT_PETAL_BACK": "FacingBack",
@@ -565,7 +582,6 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
565
582
  error_txt = []
566
583
  txt = "Click OK to add\n\t{}".format("\n\t".join(missing))
567
584
  if dbGtkUtils.ask_for_confirmation("Missing components", txt, parent=self):
568
- this_petal = self.SN.get_text()
569
585
  for cmp in missing:
570
586
  SN = components[comp_map[cmp]]
571
587
  if SN[0:5] == "20USE":
@@ -582,22 +598,6 @@ class AVSPanel(dbGtkUtils.ITkDBWindow):
582
598
  if rc is None:
583
599
  print("Could not set final stage of {} [{}]".format(ctype, SN))
584
600
 
585
- # Check for HonneyComb set
586
- for P in self.petal_core["properties"]:
587
- if P["code"] == "HC_ID" and P["value"] is None:
588
- if dbGtkUtils.is_iterable(components["HoneyCombSet"]):
589
- val = ' '.join(components["HoneyCombSet"])
590
- else:
591
- val = str(components["HoneyCombSet"])
592
- rc = ITkDButils.set_component_property(self.session,
593
- this_petal,
594
- "HC_ID",
595
- val)
596
- if rc is None:
597
- error_txt.append("Problems setting HoneyCombSet ID.\n")
598
-
599
- break
600
-
601
601
  # Check the final stage of the assembled objects
602
602
  # for child in self.petal_core["children"]:
603
603
  # if child["component"]:
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ """Analyze the table generated by createMetrologyTable."""
3
+
4
+ import sys
5
+ from pathlib import Path
6
+ import math
7
+ import argparse
8
+ import pandas as pd
9
+ import numpy as np
10
+ from numpy.linalg import norm
11
+ import matplotlib.pyplot as plt
12
+ from lmfit.models import LinearModel
13
+
14
+ from petal_qc.utils.fit_utils import draw_best_fit
15
+
16
+ def distance(P1, P2, P3):
17
+ C = np.cross(P2-P1, P3-P1)
18
+ D = C/norm(P2-P1)
19
+ return D
20
+
21
+ def remove_outliers_indx(data, cut=2.0, debug=False):
22
+ """Remove points far away form the rest.
23
+
24
+ Args:
25
+ ----
26
+ data : The data
27
+ cut: max allowed distance
28
+ debug: be verbose if True.
29
+
30
+ Returns
31
+ -------
32
+ index of valid pints in data array.
33
+
34
+ """
35
+ d = np.abs(data - np.median(data))
36
+ mdev = np.median(d)
37
+ s = d / (mdev if mdev else 1.)
38
+ indx = np.where(s < cut)[0]
39
+ return indx
40
+
41
+
42
+ def main(options):
43
+ """main entry."""
44
+ fig_width = 12.0
45
+ fig_height = 1.2*fig_width/3.0
46
+
47
+ T = pd.read_csv(options.files[0])
48
+
49
+ if options.mould > 0:
50
+ x = 1000*T.loc[T['mould'] == options.mould, 'fd_dx'].values
51
+ y = 1000*T.loc[T['mould'] == options.mould, 'fd_dy'].values
52
+
53
+ else:
54
+ x = 1000*T['fd_dx'].values
55
+ y = 1000*T['fd_dy'].values
56
+
57
+ fig, ax = plt.subplots(nrows=1, ncols=3, tight_layout=True, figsize=(fig_width, fig_height))
58
+ fig.suptitle("Relative Position FD01-FD02")
59
+ ax[0].set_title("FD01-FD02")
60
+ ax[0].set_aspect('equal', adjustable='box')
61
+ ax[0].set_xlim(-150, 150)
62
+ ax[0].set_ylim(-150, 150)
63
+ circle = plt.Circle((0,0), 75, color="red", alpha=0.25)
64
+ ax[0].add_patch(circle)
65
+ circle = plt.Circle((0,0), 25, color="green", alpha=0.25)
66
+ ax[0].add_patch(circle)
67
+
68
+ ax[0].set_xlabel("X (µm)")
69
+ ax[0].set_ylabel("Y (µm)")
70
+ ax[0].grid()
71
+
72
+ ax[0].scatter(x, y, marker='.')
73
+
74
+ model = LinearModel()
75
+ params = model.guess(y, x=x)
76
+ result = model.fit(y, params, x=x)
77
+
78
+
79
+ P1 = np.array([0, result.eval(x=0)])
80
+ P2 = np.array([1, result.eval(x=1)])
81
+ values = []
82
+ for v, w in zip(x, y):
83
+ P3 = np.array([v, w])
84
+ values.append(distance(P1, P2, P3))
85
+
86
+ indx = remove_outliers_indx(values)
87
+
88
+ xx = x[indx]
89
+ yy = y[indx]
90
+ params = model.guess(yy, xx)
91
+ result = model.fit(yy, params, x=xx)
92
+ result.plot_fit(ax=ax[0])
93
+ print("slope {:.5f}, intercept {:.5f}".format(result.best_values['slope'], result.best_values["intercept"]))
94
+ angle = 180*math.atan( result.best_values['slope'])/math.pi
95
+ print("angle {:.5f} deg.".format(angle))
96
+
97
+ ax[1].set_xlim(-150, 150)
98
+ ax[1].set_xlabel("X (µm)")
99
+ ax[1].grid()
100
+ ax[1].hist(x)
101
+
102
+ ax[2].set_xlim(-150, 150)
103
+ ax[2].set_xlabel("Y (µm)")
104
+ ax[2].grid()
105
+ ax[2].hist(y)
106
+
107
+ plt.show()
108
+
109
+ if __name__ == "__main__":
110
+ parser = argparse.ArgumentParser()
111
+ parser.add_argument('files', nargs='*', help="Input files")
112
+ parser.add_argument('--mould', default=-1, type=int, help="mould index")
113
+
114
+ opts = parser.parse_args()
115
+ if len(opts.files) == 0:
116
+ print("I need at least one input file")
117
+ sys.exit()
118
+
119
+ main(opts)
@@ -169,8 +169,8 @@ if __name__ == "__main__":
169
169
  client = dlg.get_client()
170
170
 
171
171
  try:
172
- # main(session)
173
- the_test = analyze_avs_metrology(client, "20USEBC1000124", "PPC.015")
172
+ main(client)
173
+ # the_test = analyze_avs_metrology(client, "20USEBC1000124", "PPC.015")
174
174
  #rc = ITkDButils.upload_test(client, the_test, check_runNumber=True)
175
175
  #if rc:
176
176
  # print(rc)