pigeon-tem-comms 0.1.1__tar.gz → 0.3.0__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 (26) hide show
  1. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/PKG-INFO +1 -1
  2. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/__init__.py +5 -1
  3. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/camera.py +8 -1
  4. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/scope.py +2 -1
  5. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/stage/__init__.py +1 -1
  6. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/stage/aperture.py +3 -1
  7. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/stage/motion.py +3 -1
  8. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/stage/rotation.py +3 -1
  9. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/tile/statistics.py +4 -1
  10. pigeon_tem_comms-0.3.0/TEM_comms/ui.py +42 -0
  11. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/PKG-INFO +1 -1
  12. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/SOURCES.txt +3 -1
  13. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pyproject.toml +1 -1
  14. pigeon_tem_comms-0.3.0/tests/test_buffer.py +64 -0
  15. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/tests/test_scope_command.py +4 -2
  16. pigeon_tem_comms-0.3.0/tests/test_ui.py +18 -0
  17. pigeon_tem_comms-0.1.1/tests/test_buffer.py +0 -41
  18. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/LICENSE +0 -0
  19. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/README.md +0 -0
  20. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/buffer.py +0 -0
  21. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/TEM_comms/tile/__init__.py +0 -0
  22. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/dependency_links.txt +0 -0
  23. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/entry_points.txt +0 -0
  24. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/requires.txt +0 -0
  25. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/pigeon_tem_comms.egg-info/top_level.txt +0 -0
  26. {pigeon_tem_comms-0.1.1 → pigeon_tem_comms-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pigeon-tem-comms
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: Pigeon messages for the next generation TEM imaging system.
5
5
  Author-email: Cameron Devine <cameron.devine@alleninstitute.org>
6
6
  License: BSD 3 Clause
@@ -3,6 +3,7 @@ from . import camera
3
3
  from . import scope
4
4
  from . import stage
5
5
  from . import tile
6
+ from . import ui
6
7
 
7
8
  import importlib.metadata
8
9
 
@@ -31,7 +32,10 @@ topics = {
31
32
  "tile.statistics.histogram": tile.statistics.Histogram,
32
33
  "tile.statistics.min_max_mean": tile.statistics.MinMaxMean,
33
34
  "tile.transform": tile.Transform,
35
+ "ui.edit": ui.Edit,
36
+ "ui.run": ui.Run,
37
+ "ui.setup": ui.Setup,
34
38
  }
35
39
 
36
40
 
37
- msgs = (topics, __version__)
41
+ msgs = (topics, __version__)
@@ -1,23 +1,30 @@
1
1
  from pigeon import BaseMessage
2
+ from typing import Optional
3
+
2
4
 
3
5
  class Command(BaseMessage):
4
6
  tile_id: str
5
7
 
8
+
6
9
  class Image(BaseMessage):
7
10
  tile_id: str
8
11
  path: str
9
12
 
13
+
10
14
  class Settings(BaseMessage):
11
15
  exposure: float | None = None
16
+ gain: Optional[float] = None
12
17
  width: int | None = None
13
18
  height: int | None = None
14
19
 
20
+
15
21
  class Status(BaseMessage):
16
22
  exposure: float
23
+ gain: float
17
24
  width: int
18
25
  height: int
19
26
  temp: float
20
27
  target_temp: float
21
28
  device_name: str
22
29
  device_model_id: int
23
- device_sn: str
30
+ device_sn: str
@@ -2,6 +2,7 @@ from pigeon import BaseMessage
2
2
  from typing import Literal
3
3
  from pydantic import model_validator
4
4
 
5
+
5
6
  class Command(BaseMessage):
6
7
  focus: int | None = None
7
8
  mag_mode: Literal["LM", "MAG1", "MAG2"] | None = None
@@ -18,4 +19,4 @@ class Status(BaseMessage):
18
19
  aperture: str | None
19
20
  mag_mode: str
20
21
  mag: int
21
- tank_voltage: int
22
+ tank_voltage: int
@@ -1,3 +1,3 @@
1
1
  from . import aperture
2
2
  from . import motion
3
- from . import rotation
3
+ from . import rotation
@@ -1,10 +1,12 @@
1
1
  from pigeon import BaseMessage
2
2
 
3
+
3
4
  class Command(BaseMessage):
4
5
  aperture_id: int | None = None
5
6
  calibrate: bool = False
6
7
 
8
+
7
9
  class Status(BaseMessage):
8
10
  current_aperture: int
9
11
  calibrated: bool
10
- error: str = ""
12
+ error: str = ""
@@ -1,12 +1,14 @@
1
1
  from pigeon import BaseMessage
2
2
 
3
+
3
4
  class Command(BaseMessage):
4
5
  x: int | None = None
5
6
  y: int | None = None
6
7
  calibrate: bool = False
7
8
 
9
+
8
10
  class Status(BaseMessage):
9
11
  x: int
10
12
  y: int
11
13
  in_motion: bool
12
- error: str = ""
14
+ error: str = ""
@@ -1,12 +1,14 @@
1
1
  from pigeon import BaseMessage
2
2
 
3
+
3
4
  class Command(BaseMessage):
4
5
  angle_x: float | None = None
5
6
  angle_y: float | None = None
6
7
  calibrate: bool = False
7
8
 
9
+
8
10
  class Status(BaseMessage):
9
11
  angle_x: float
10
12
  angle_y: float
11
13
  in_motion: bool
12
- error: str = ""
14
+ error: str = ""
@@ -1,15 +1,18 @@
1
1
  from pigeon import BaseMessage
2
2
 
3
+
3
4
  class Focus(BaseMessage):
4
5
  tile_id: str
5
6
  focus: float
6
7
 
8
+
7
9
  class Histogram(BaseMessage):
8
10
  tile_id: str
9
11
  path: str
10
12
 
13
+
11
14
  class MinMaxMean(BaseMessage):
12
15
  tile_id: str
13
16
  min: int
14
17
  max: int
15
- mean: int
18
+ mean: int
@@ -0,0 +1,42 @@
1
+ from pigeon import BaseMessage
2
+ from typing import Optional
3
+ from pydantic import model_validator
4
+
5
+
6
+ class Edit(BaseMessage):
7
+ roi_id: str
8
+ roi_pos_x: int
9
+ roi_pox_y: int
10
+ roi_width: int
11
+ roi_height: int
12
+ roi_angle: float
13
+
14
+
15
+ class Run(BaseMessage):
16
+ session_id: Optional[str] = None
17
+ grid_first: Optional[int] = None
18
+ grid_last: Optional[int] = None
19
+ montage: bool = False
20
+ abort_now: bool = False
21
+ abort_at_end: bool = False
22
+ resume: bool = False
23
+
24
+ @model_validator(mode="after")
25
+ def check_grid(self):
26
+ assert self.montage != (self.grid_first is None)
27
+ assert self.montage != (self.grid_last is None)
28
+ return self
29
+
30
+ @model_validator(mode="after")
31
+ def check_session(self):
32
+ assert self.montage != (self.session_id is None)
33
+ return self
34
+
35
+
36
+ class Setup(BaseMessage):
37
+ conch_owner: Optional[str] = None
38
+ auto_focus: bool = False
39
+ auto_exposure: bool = False
40
+ lens_correction: bool = False
41
+ acquire_brightfield: bool = False
42
+ acquire_darkfield: bool = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pigeon-tem-comms
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: Pigeon messages for the next generation TEM imaging system.
5
5
  Author-email: Cameron Devine <cameron.devine@alleninstitute.org>
6
6
  License: BSD 3 Clause
@@ -5,6 +5,7 @@ TEM_comms/__init__.py
5
5
  TEM_comms/buffer.py
6
6
  TEM_comms/camera.py
7
7
  TEM_comms/scope.py
8
+ TEM_comms/ui.py
8
9
  TEM_comms/stage/__init__.py
9
10
  TEM_comms/stage/aperture.py
10
11
  TEM_comms/stage/motion.py
@@ -18,4 +19,5 @@ pigeon_tem_comms.egg-info/entry_points.txt
18
19
  pigeon_tem_comms.egg-info/requires.txt
19
20
  pigeon_tem_comms.egg-info/top_level.txt
20
21
  tests/test_buffer.py
21
- tests/test_scope_command.py
22
+ tests/test_scope_command.py
23
+ tests/test_ui.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pigeon-tem-comms"
3
- version = "0.1.1"
3
+ version = "0.3.0"
4
4
  authors = [
5
5
  { name="Cameron Devine", email="cameron.devine@alleninstitute.org" },
6
6
  ]
@@ -0,0 +1,64 @@
1
+ import re
2
+
3
+ import pytest
4
+ from TEM_comms.buffer import Status
5
+
6
+ from pydantic import ValidationError
7
+
8
+
9
+ # Test cases for the Status class
10
+ @pytest.mark.parametrize(
11
+ "queue_length, free_space, upload_rate, test_id",
12
+ [
13
+ (10, 100, 20, "test_id_01"), # Happy path: normal values
14
+ (0, 0, 0, "test_id_02"), # Edge case: zero values
15
+ (100, 500, 100, "test_id_03"), # Happy path: higher values
16
+ (-1, -100, -10, "test_id_04"), # Error case: negative values
17
+ (1e6, 1e6, 1e4, "test_id_05"), # Edge case: very large values
18
+ ],
19
+ )
20
+ def test_status_initialization(queue_length, free_space, upload_rate, test_id):
21
+ # Act
22
+ status = Status(
23
+ queue_length=queue_length, free_space=free_space, upload_rate=upload_rate
24
+ )
25
+
26
+ # Assert
27
+ assert (
28
+ status.queue_length == queue_length
29
+ ), f"{test_id}: queue_length does not match"
30
+ assert status.free_space == free_space, f"{test_id}: free_space does not match"
31
+ assert status.upload_rate == upload_rate, f"{test_id}: upload_rate does not match"
32
+
33
+
34
+ # Test cases for handling type errors
35
+ @pytest.mark.parametrize(
36
+ "queue_length, free_space, upload_rate, test_id",
37
+ [
38
+ (
39
+ "ten",
40
+ 100,
41
+ 20,
42
+ "test_id_06",
43
+ ), # Error case: string instead of int for queue_length
44
+ (
45
+ 10,
46
+ "hundred",
47
+ 20,
48
+ "test_id_07",
49
+ ), # Error case: string instead of int for free_space
50
+ (
51
+ 10,
52
+ 100,
53
+ "twenty",
54
+ "test_id_08",
55
+ ), # Error case: string instead of int for upload_rate
56
+ ],
57
+ )
58
+ def test_status_type_errors(queue_length, free_space, upload_rate, test_id):
59
+ # Act and Assert
60
+ expected_error_pattern = re.escape("validation error")
61
+ with pytest.raises(ValidationError, match=expected_error_pattern):
62
+ Status(
63
+ queue_length=queue_length, free_space=free_space, upload_rate=upload_rate
64
+ )
@@ -2,20 +2,22 @@ from TEM_comms.scope import Command
2
2
  from pydantic import ValidationError
3
3
  import pytest
4
4
 
5
+
5
6
  def test_mag():
6
7
  with pytest.raises(ValidationError):
7
8
  Command(mag_mode="LM")
8
-
9
+
9
10
  with pytest.raises(ValidationError):
10
11
  Command(mag=10)
11
12
 
12
13
  Command()
13
14
  Command(mag_mode="LM", mag=1)
14
15
 
16
+
15
17
  def test_mag_mode():
16
18
  with pytest.raises(ValidationError):
17
19
  Command(mag_mode="test", mag=1)
18
20
 
19
21
  Command(mag_mode="LM", mag=1)
20
22
  Command(mag_mode="MAG2", mag=1)
21
- Command(mag_mode="MAG2", mag=1)
23
+ Command(mag_mode="MAG2", mag=1)
@@ -0,0 +1,18 @@
1
+ from TEM_comms.ui import Run
2
+ from pydantic import ValidationError
3
+ import pytest
4
+
5
+
6
+ def test_run():
7
+ with pytest.raises(ValidationError):
8
+ Run(montage=True, session_id="test", grid_first=1)
9
+
10
+ with pytest.raises(ValidationError):
11
+ Run(montage=True, session_id="test", grid_last=2)
12
+
13
+ with pytest.raises(ValidationError):
14
+ Run(montage=True, grid_first=1, grid_last=2)
15
+
16
+ Run(montage=True, session_id="test", grid_first=1, grid_last=2)
17
+ msg = Run()
18
+ assert not msg.montage
@@ -1,41 +0,0 @@
1
- import re
2
-
3
- import pytest
4
- from TEM_comms.buffer import Status
5
-
6
- from pydantic import ValidationError
7
-
8
- # Test cases for the Status class
9
- @pytest.mark.parametrize(
10
- "queue_length, free_space, upload_rate, test_id",
11
- [
12
- (10, 100, 20, "test_id_01"), # Happy path: normal values
13
- (0, 0, 0, "test_id_02"), # Edge case: zero values
14
- (100, 500, 100, "test_id_03"), # Happy path: higher values
15
- (-1, -100, -10, "test_id_04"), # Error case: negative values
16
- (1e6, 1e6, 1e4, "test_id_05"), # Edge case: very large values
17
- ]
18
- )
19
- def test_status_initialization(queue_length, free_space, upload_rate, test_id):
20
- # Act
21
- status = Status(queue_length=queue_length, free_space=free_space, upload_rate=upload_rate)
22
-
23
- # Assert
24
- assert status.queue_length == queue_length, f"{test_id}: queue_length does not match"
25
- assert status.free_space == free_space, f"{test_id}: free_space does not match"
26
- assert status.upload_rate == upload_rate, f"{test_id}: upload_rate does not match"
27
-
28
- # Test cases for handling type errors
29
- @pytest.mark.parametrize(
30
- "queue_length, free_space, upload_rate, test_id",
31
- [
32
- ("ten", 100, 20, "test_id_06"), # Error case: string instead of int for queue_length
33
- (10, "hundred", 20, "test_id_07"), # Error case: string instead of int for free_space
34
- (10, 100, "twenty", "test_id_08"), # Error case: string instead of int for upload_rate
35
- ]
36
- )
37
- def test_status_type_errors(queue_length, free_space, upload_rate, test_id):
38
- # Act and Assert
39
- expected_error_pattern = re.escape("validation error")
40
- with pytest.raises(ValidationError, match=expected_error_pattern):
41
- Status(queue_length=queue_length, free_space=free_space, upload_rate=upload_rate)