etlup 4.3.0__tar.gz → 4.3.2__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.
Files changed (52) hide show
  1. {etlup-4.3.0 → etlup-4.3.2}/PKG-INFO +1 -1
  2. {etlup-4.3.0 → etlup-4.3.2}/pyproject.toml +1 -1
  3. etlup-4.3.2/src/etlup/hybrid/HybridVisualInspection.py +96 -0
  4. etlup-4.3.2/src/etlup/hybrid/ProbeCardI2CConnection.py +73 -0
  5. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/SensorIV.py +29 -1
  6. {etlup-4.3.0 → etlup-4.3.2}/README.md +0 -0
  7. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/__about__.py +0 -0
  8. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/__init__.py +0 -0
  9. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/base_model.py +0 -0
  10. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/custom_types.py +0 -0
  11. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/example_formatter.py +0 -0
  12. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/fake/__init__.py +0 -0
  13. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/fake/fake_test_component.py +0 -0
  14. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/fake/fake_test_module.py +0 -0
  15. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/gantry/PickAndPlace.py +0 -0
  16. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/gantry/SubassemblyAlignment.py +0 -0
  17. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/gantry/__init__.py +0 -0
  18. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/ETROCOpticalInspection.py +0 -0
  19. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/HybridBaseline.py +0 -0
  20. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/HybridIV.py +0 -0
  21. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/HybridNoisewidth.py +0 -0
  22. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/XRayInspection.py +0 -0
  23. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/hybrid/__init__.py +0 -0
  24. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/image_tests/ImageTest.py +0 -0
  25. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/image_tests/__init__.py +0 -0
  26. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/module/ModuleIV.py +0 -0
  27. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/module/ModulePcbOpticalInspection.py +0 -0
  28. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/module/__init__.py +0 -0
  29. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/plot_utils.py +0 -0
  30. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/ChargeCollection.py +0 -0
  31. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/CurrentStability.py +0 -0
  32. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/CurrentUniformity.py +0 -0
  33. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/GainCurve.py +0 -0
  34. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/GainLayerUniformity.py +0 -0
  35. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/InterpadResistance.py +0 -0
  36. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/InterpadWidth.py +0 -0
  37. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/MPVStability.py +0 -0
  38. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/OpticalInspection.py +0 -0
  39. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/SensorIrradiation.py +0 -0
  40. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/TestArrayCV.py +0 -0
  41. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/TestArrayIV.py +0 -0
  42. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/TimeResolution.py +0 -0
  43. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sensor/__init__.py +0 -0
  44. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/sequences.py +0 -0
  45. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/tamalero/Baseline.py +0 -0
  46. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/tamalero/Mux64Values.py +0 -0
  47. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/tamalero/Noisewidth.py +0 -0
  48. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/tamalero/ReadoutBoardCommunication.py +0 -0
  49. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/tamalero/__init__.py +0 -0
  50. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/templates/sensors_plot.html +0 -0
  51. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/templates/test_by_image.html +0 -0
  52. {etlup-4.3.0 → etlup-4.3.2}/src/etlup/upload.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etlup
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Summary: Test definitions, plotting and documentation for the CMS MTD ETL project
5
5
  Author: Hayden Swanson
6
6
  Author-email: Hayden Swanson <hayden.swanson@cern.ch>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "etlup"
3
- version = "4.3.0"
3
+ version = "4.3.2"
4
4
  description = "Test definitions, plotting and documentation for the CMS MTD ETL project"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.8"
@@ -0,0 +1,96 @@
1
+ from pydantic import ConfigDict, Field
2
+ from typing_extensions import Annotated, Literal, Union, Optional
3
+
4
+ from .. import base_model as bm, jinja_env
5
+ from ..custom_types import Image
6
+ from ..plot_utils import image_src
7
+
8
+ # How much residue is left on the pads, from none at all to a lot of it.
9
+ PadResidue = Literal['Clean', 'Light', 'Moderate', 'Heavy']
10
+
11
+ # A 1x1 PNG, just enough for the example below to be a real image.
12
+ _EXAMPLE_IMAGE = (
13
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGO4AAAA0gDR29kOtwAAAABJRU5ErkJggg=="
14
+ )
15
+
16
+ class HybridVisualInspectionV0(bm.ConstructionBase):
17
+ model_config = ConfigDict(json_schema_extra={
18
+ 'examples': [
19
+ {
20
+ "component": "ET2.01-PT-NH21",
21
+ "name": "hybrid_visual_inspection",
22
+ "location": "KNU",
23
+ "user_created": "ypark",
24
+ "version": "v0",
25
+ "measurement_date": "2026-07-29T12:01:00+02:00",
26
+ "pad_residue": "Light",
27
+ "bump_damage": False,
28
+ "mechanical_damage": False,
29
+ "shifted_hybrids": False,
30
+ "image": _EXAMPLE_IMAGE,
31
+ "comment": "A little residue on the top left pads, otherwise fine.",
32
+ "passed": True,
33
+ },
34
+ {
35
+ "component": "ET2.01-PT-NH22",
36
+ "name": "hybrid_visual_inspection",
37
+ "location": "KNU",
38
+ "user_created": "ypark",
39
+ "version": "v0",
40
+ "measurement_date": "2026-07-29T12:05:00+02:00",
41
+ "mechanical_damage": True,
42
+ "passed": False,
43
+ },
44
+ ],
45
+ 'table': 'test',
46
+ 'category': 'Subassembly',
47
+ 'component_types': [],
48
+ 'module_types': [],
49
+ 'description': (
50
+ 'Visual inspection of a hybrid. Records how much residue is on the pads '
51
+ '(Clean, Light, Moderate or Heavy), whether there is bump damage, mechanical damage '
52
+ 'or shifted hybrids, an overall passed verdict, and optionally a photograph, base64 '
53
+ 'encoded, and a comment. Every field is optional, so only what was looked at needs to be sent.'
54
+ )
55
+ })
56
+
57
+ name: Literal['hybrid_visual_inspection'] = 'hybrid_visual_inspection'
58
+ version: Literal["v0"] = "v0"
59
+ component: str
60
+
61
+ # None means it was not looked at, not that it was fine.
62
+ pad_residue: Optional[PadResidue] = None
63
+ bump_damage: Optional[bool] = None
64
+ mechanical_damage: Optional[bool] = None
65
+ shifted_hybrids: Optional[bool] = None
66
+ image: Optional[Image] = None
67
+ comment: Optional[str] = None
68
+ passed: Optional[bool] = None # None until somebody decides
69
+
70
+ def plot(self):
71
+ return None
72
+
73
+ def html_display(self) -> str:
74
+ display_data = {
75
+ "passed": self.passed,
76
+ "pad_residue": self.pad_residue,
77
+ "bump_damage": self.bump_damage,
78
+ "mechanical_damage": self.mechanical_damage,
79
+ "shifted_hybrids": self.shifted_hybrids,
80
+ "comment": self.comment,
81
+ }
82
+ if self.image is None:
83
+ img_html = "<p>No image was given with this inspection.</p>"
84
+ else:
85
+ img_html = (
86
+ f'<img src="{image_src(self.image)}" alt="{self.component} visual inspection" '
87
+ 'style="width: clamp(300px, 75vw, 1000px); height: auto;">'
88
+ )
89
+ template = jinja_env.get_template('test_by_image.html')
90
+ return template.render(
91
+ display_data=display_data,
92
+ img_html=img_html
93
+ )
94
+
95
+
96
+ HybridVisualInspectionType = Annotated[Union[HybridVisualInspectionV0], Field(discriminator="version")]
@@ -0,0 +1,73 @@
1
+ from pydantic import ConfigDict, Field
2
+ from typing_extensions import Annotated, Literal, Union, Optional
3
+
4
+ from .. import base_model as bm, jinja_env
5
+
6
+ class ProbeCardI2CConnectionV0(bm.ConstructionBase):
7
+ model_config = ConfigDict(json_schema_extra={
8
+ 'examples': [
9
+ {
10
+ "component": "ET2.01-PT-NH21",
11
+ "name": "probe_card_i2c_connection",
12
+ "location": "KNU",
13
+ "user_created": "ypark",
14
+ "version": "v0",
15
+ "measurement_date": "2026-07-29T12:01:00+02:00",
16
+ "i2c_connection": True,
17
+ "current_digital": 0.12,
18
+ "current_analog": 0.35,
19
+ "comment": None,
20
+ "passed": True,
21
+ },
22
+ {
23
+ "component": "ET2.01-PT-NH22",
24
+ "name": "probe_card_i2c_connection",
25
+ "location": "KNU",
26
+ "user_created": "ypark",
27
+ "version": "v0",
28
+ "measurement_date": "2026-07-29T12:05:00+02:00",
29
+ "i2c_connection": False,
30
+ "comment": "No I2C response from the ETROC.",
31
+ "passed": False,
32
+ },
33
+ ],
34
+ 'table': 'test',
35
+ 'category': 'Subassembly',
36
+ 'component_types': [],
37
+ 'module_types': [],
38
+ 'description': (
39
+ 'Checks that a hybrid talks over I2C on the probe card. Records whether the I2C '
40
+ 'connection was made, an overall passed verdict, and optionally the digital and analog '
41
+ 'currents drawn and a comment.'
42
+ )
43
+ })
44
+
45
+ name: Literal['probe_card_i2c_connection'] = 'probe_card_i2c_connection'
46
+ version: Literal["v0"] = "v0"
47
+ component: str
48
+
49
+ i2c_connection: bool
50
+ current_digital: Optional[float] = None
51
+ current_analog: Optional[float] = None
52
+ comment: Optional[str] = None
53
+ passed: Optional[bool] = None # None until somebody decides
54
+
55
+ def plot(self):
56
+ return None
57
+
58
+ def html_display(self) -> str:
59
+ display_data = {
60
+ "passed": self.passed,
61
+ "i2c_connection": self.i2c_connection,
62
+ "current_digital": self.current_digital,
63
+ "current_analog": self.current_analog,
64
+ "comment": self.comment,
65
+ }
66
+ template = jinja_env.get_template('test_by_image.html')
67
+ return template.render(
68
+ display_data=display_data,
69
+ img_html=""
70
+ )
71
+
72
+
73
+ ProbeCardI2CConnectionType = Annotated[Union[ProbeCardI2CConnectionV0], Field(discriminator="version")]
@@ -81,4 +81,32 @@ class SensorIVV0(base_model.ConstructionBase):
81
81
  display_data = display_data
82
82
  )
83
83
 
84
- SensorIVType = Annotated[Union[SensorIVV0], Field(discriminator="version")]
84
+ class SensorIVV1(SensorIVV0):
85
+ model_config = ConfigDict(json_schema_extra={
86
+ 'examples': [
87
+ {
88
+ "component": "FBK_LF1_ROL_054",
89
+ "name": "Sensor IV",
90
+ "measurement_date": "2023-01-01T12:00:00+01:00",
91
+ "location": "UT",
92
+ "user_created": "fsiviero",
93
+ "version": "v1",
94
+ "leakage_current_uA": 158.176,
95
+ "breakdown_voltage_V": 282.0,
96
+ "category": "BAD",
97
+ "gain_category": "BD3",
98
+ "current": [1.798e-9, 2.132e-9,2.389e-9,2.667e-9,2.991e-9,3.373e-9,3.882e-9,4.470e-9,5.163e-9,5.98e-9,6.888e-9,7.861e-9,8.972e-9,9.177e-9,1.135e-8,1.334e-8,1.591e-8,1.956e-8,2.418e-8,2.950e-8,4.237e-8,5.572e-6,0.0000257,0.0000342,0.0000405,0.0000441,0.0000454,0.0000519,0.0000652,0.0000757,0.00008891,0.0001137,0.000133,0.000151,0.000165,0.0001832,0.000201,0.000213,0.000224,0.000234,0.000245,0.000256,0.000271,0.000286,0.000301,0.000313,0.000325,0.000337,0.000349,0.000371],
99
+ "voltage": [0.0,2.0,4.0,6.0,8.0,10.0,12.0,14.0,16.0,18.0,20.0,22.0,23.0,25.0,26.0,28.0,30.0,32.0,34.0,36.0,38.0,40.0,41.0,43.0,45.0,47.0,49.0,50.0,55.0,60.0,65.0,70.0,75.0,80.0,85.0,90.0,95.0,100.0,105.0,110.0,115.0,120.0,125.0,130.0,135.0,140.0,145.0,150.0,155.0,160.0],
100
+ }
101
+ ],
102
+ 'table': 'test',
103
+ 'category': 'LGAD',
104
+ 'component_types': [],
105
+ 'module_types': [],
106
+ 'description': 'IV curves and other QC info of the sensors recieved from a vendor and tested by ETL sensor experts'
107
+ })
108
+
109
+ version: Literal["v1"] = "v1"
110
+ gain_category: Union[None, Literal["BD1", "BD2", "BD3", "BD4", "BD5", "BD6", "BD7", "BD8", "BD9", "BD10"]] = Field(None, validation_alias=AliasChoices('gain_category','Gain Category'))
111
+
112
+ SensorIVType = Annotated[Union[SensorIVV0, SensorIVV1], Field(discriminator="version")]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes