pyobs-aravis 1.1.3__tar.gz → 2.0.0.dev2__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.
@@ -0,0 +1,26 @@
1
+ name: ruff
2
+ on: push
3
+
4
+ jobs:
5
+ ruff:
6
+ runs-on: ubuntu-latest
7
+ timeout-minutes: 10
8
+
9
+ steps:
10
+ - name: Check out repository code
11
+ uses: actions/checkout@v4
12
+
13
+ - name: Set up Python
14
+ uses: astral-sh/setup-uv@v5
15
+ with:
16
+ enable-cache: true
17
+ python-version: "3.13"
18
+
19
+ - name: Install system dependencies
20
+ run: sudo apt-get install -y python3-gi python3-gi-cairo gir1.2-aravis-0.8
21
+
22
+ - name: Install packages
23
+ run: uv venv --system-site-packages .venv && uv sync --all-extras --dev
24
+
25
+ - name: Run ruff
26
+ run: uv run --no-sync ruff check pyobs_aravis/
@@ -0,0 +1,10 @@
1
+ repos:
2
+ - repo: https://github.com/psf/black-pre-commit-mirror
3
+ rev: 25.1.0
4
+ hooks:
5
+ - id: black
6
+ language_version: python3.11
7
+ - repo: https://github.com/astral-sh/ruff-pre-commit
8
+ rev: v0.9.0
9
+ hooks:
10
+ - id: ruff
@@ -1,11 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyobs-aravis
3
- Version: 1.1.3
3
+ Version: 2.0.0.dev2
4
4
  Summary: pyobs module for Aravis cameras
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
7
7
  License-File: LICENSE
8
- Requires-Python: >=3.11
9
- Requires-Dist: numpy~=1.21
10
- Requires-Dist: pygobject~=3.42
11
- Requires-Dist: pyobs-core~=1.0
8
+ Requires-Python: <3.14,>=3.11
9
+ Requires-Dist: numpy<3,>=2.2.5
10
+ Requires-Dist: pyobs-core<3,>=2.0.0.dev1
@@ -0,0 +1,50 @@
1
+ *pyobs* for Aravis cameras
2
+ ==========================
3
+
4
+ This is a [pyobs](https://www.pyobs.org) module for cameras supported by the
5
+ [Aravis](https://github.com/AravisProject/aravis) library (GenICam/GigE Vision/USB3 Vision cameras).
6
+
7
+
8
+ System dependencies
9
+ --------------------
10
+ Aravis and its GObject introspection bindings are not pip-installable, so they need to be installed via your
11
+ system's package manager before installing *pyobs-aravis*.
12
+
13
+ On Debian/Ubuntu:
14
+
15
+ sudo apt-get install python3-gi python3-gi-cairo gir1.2-aravis-0.8
16
+
17
+ This provides:
18
+ * **Aravis** itself, together with its GObject introspection typelib (`gir1.2-aravis-0.8`).
19
+ * **PyGObject** (`python3-gi`, `python3-gi-cairo`), the `gi` module used to access Aravis from Python.
20
+
21
+ Since these packages are installed system-wide, your virtual environment needs access to the system
22
+ site-packages so it can find the `gi` module.
23
+
24
+
25
+ Install *pyobs-aravis*
26
+ -----------------------
27
+ Clone the repository:
28
+
29
+ git clone https://github.com/pyobs/pyobs-aravis.git
30
+ cd pyobs-aravis
31
+
32
+ Create a virtual environment with access to the system site-packages and install the package with
33
+ [uv](https://docs.astral.sh/uv/):
34
+
35
+ uv venv --system-site-packages
36
+ uv sync
37
+
38
+ Alternatively, with plain `venv`/`pip`:
39
+
40
+ python3 -m venv --system-site-packages .venv
41
+ source .venv/bin/activate
42
+ pip install .
43
+
44
+
45
+ Dependencies
46
+ ------------
47
+ * [pyobs-core](https://github.com/pyobs/pyobs-core) for the core functionality.
48
+ * [numpy](https://numpy.org/) for handling image data.
49
+ * [Aravis](https://github.com/AravisProject/aravis) and [PyGObject](https://pygobject.readthedocs.io/) for
50
+ accessing the camera, installed via the system's package manager (see above).
@@ -0,0 +1,3 @@
1
+ from .araviscamera import AravisCamera as AravisCamera
2
+
3
+ __all__ = ["AravisCamera"]
@@ -1,13 +1,12 @@
1
1
  import asyncio
2
2
  import logging
3
3
  import time
4
- import numpy.typing as npt
5
- from typing import Any, Dict, Optional, List
4
+ from typing import Any
6
5
 
7
- from pyobs.interfaces import IExposureTime
6
+ import numpy.typing as npt
7
+ from pyobs.interfaces import ExposureTimeState, IExposureTime
8
8
  from pyobs.modules.camera import BaseVideo
9
9
 
10
-
11
10
  log = logging.getLogger(__name__)
12
11
 
13
12
 
@@ -19,7 +18,7 @@ class AravisCamera(BaseVideo, IExposureTime):
19
18
  def __init__(
20
19
  self,
21
20
  device: str,
22
- settings: Optional[Dict[str, Any]] = None,
21
+ settings: dict[str, Any] | None = None,
23
22
  buffers: int = 5,
24
23
  **kwargs: Any,
25
24
  ):
@@ -27,18 +26,18 @@ class AravisCamera(BaseVideo, IExposureTime):
27
26
 
28
27
  Args:
29
28
  device: Name of camera to connect to.
29
+ settings: Dictionary of camera settings to apply on connect.
30
+ buffers: Number of acquisition buffers.
30
31
  """
31
32
  BaseVideo.__init__(self, **kwargs)
32
33
  from . import aravis
33
34
 
34
- # variables
35
35
  self._device_name = device
36
- self._camera: Optional[aravis.Camera] = None
37
- self._settings: Dict[str, Any] = {} if settings is None else settings
36
+ self._camera: aravis.Camera | None = None
37
+ self._settings: dict[str, Any] = {} if settings is None else settings
38
38
  self._camera_lock = asyncio.Lock()
39
39
  self._buffers = buffers
40
40
 
41
- # thread
42
41
  if device is not None:
43
42
  self.add_background_task(self._capture)
44
43
  else:
@@ -48,17 +47,12 @@ class AravisCamera(BaseVideo, IExposureTime):
48
47
  """Open module."""
49
48
  from . import aravis
50
49
 
51
- # open base
52
50
  await BaseVideo.open(self)
53
51
 
54
- # list devices
55
- ids: List[str] = aravis.get_device_ids() # type: ignore
52
+ ids: list[str] = aravis.get_device_ids() # type: ignore[assignment]
56
53
  if self._device_name not in ids:
57
- raise ValueError(
58
- "Could not find given device name in list of available cameras."
59
- )
54
+ raise ValueError("Could not find given device name in list of available cameras.")
60
55
 
61
- # open camera
62
56
  await self.activate_camera()
63
57
 
64
58
  async def close(self) -> None:
@@ -71,92 +65,67 @@ class AravisCamera(BaseVideo, IExposureTime):
71
65
  """Open camera."""
72
66
  from . import aravis
73
67
 
74
- # open camera
75
68
  log.info("Connecting to camera %s...", self._device_name)
76
- self._camera = aravis.Camera(self._device_name) # type: ignore
69
+ self._camera = aravis.Camera(self._device_name) # type: ignore[assignment]
77
70
  log.info("Connected.")
78
71
 
79
- # settings
80
72
  for key, value in self._settings.items():
81
- log.info(f"Setting value {key}={value}...")
82
- self._camera.set_feature(key, value) # type: ignore
73
+ log.info("Setting value %s=%s...", key, value)
74
+ self._camera.set_feature(key, value) # type: ignore[union-attr]
83
75
 
84
- # start acquisition
85
- self._camera.start_acquisition_continuous(nb_buffers=self._buffers) # type: ignore
76
+ self._camera.start_acquisition_continuous(nb_buffers=self._buffers) # type: ignore[union-attr]
86
77
 
87
78
  def _close_camera(self) -> None:
88
79
  """Close camera."""
89
- # stop camera
90
80
  if self._camera is not None:
91
81
  log.info("Closing camera...")
92
- self._camera.stop_acquisition() # type: ignore
93
- self._camera.shutdown() # type: ignore
82
+ self._camera.stop_acquisition() # type: ignore[union-attr]
83
+ self._camera.shutdown() # type: ignore[union-attr]
94
84
  self._camera = None
95
85
 
96
86
  async def _activate_camera(self) -> None:
97
- """Can be overridden by derived class to implement inactivity sleep"""
87
+ """Open camera on activation."""
98
88
  async with self._camera_lock:
99
89
  self._open_camera()
100
90
 
101
91
  async def _deactivate_camera(self) -> None:
102
- """Can be overridden by derived class to implement inactivity sleep"""
92
+ """Close camera on deactivation."""
103
93
  async with self._camera_lock:
104
94
  self._close_camera()
105
95
 
106
96
  async def _capture(self) -> None:
107
97
  """Take new images in loop."""
108
-
109
- # loop until closing
110
98
  last = time.time()
111
99
  while True:
112
- # no camera or not active?
113
- if self._camera is None or not self.camera_active:
114
- # wait a little
115
- await asyncio.sleep(0.1)
116
- continue
117
-
118
- # read frame
119
- while True:
120
- frame: npt.NDArray[float] = self._camera.pop_frame() # type: ignore
121
- if frame is None:
100
+ try:
101
+ if self._camera is None or not self.camera_active:
102
+ await asyncio.sleep(0.1)
103
+ continue
104
+
105
+ frame: npt.NDArray[Any] = self._camera.pop_frame() # type: ignore[union-attr]
106
+ while frame is None:
122
107
  await asyncio.sleep(0.01)
123
- else:
124
- break
108
+ frame = self._camera.pop_frame() # type: ignore[union-attr]
125
109
 
126
- # if time since last image is too short, wait a little
127
- if time.time() - last < self._interval:
128
- await asyncio.sleep(0.01)
129
- continue
110
+ if time.time() - last < self._interval:
111
+ await asyncio.sleep(0.01)
112
+ continue
130
113
 
131
- # save time
132
- last = time.time()
114
+ last = time.time()
115
+ await self._set_image(frame)
133
116
 
134
- # process it
135
- await self._set_image(frame)
117
+ except Exception:
118
+ await asyncio.sleep(1)
136
119
 
137
120
  async def set_exposure_time(self, exposure_time: float, **kwargs: Any) -> None:
138
121
  """Set the exposure time in seconds.
139
122
 
140
123
  Args:
141
124
  exposure_time: Exposure time in seconds.
142
-
143
- Raises:
144
- ValueError: If exposure time could not be set.
145
- """
146
- await self.activate_camera()
147
- self._camera.set_exposure_time(exposure_time * 1e6) # type: ignore
148
-
149
- async def get_exposure_time(self, **kwargs: Any) -> float:
150
- """Returns the exposure time in seconds.
151
-
152
- Returns:
153
- Exposure time in seconds.
154
125
  """
155
126
  await self.activate_camera()
156
- return self._camera.get_exposure_time() / 1e6 # type: ignore
157
-
158
- async def get_exposure_time_left(self, **kwargs: Any) -> float:
159
- return 0.0
127
+ self._camera.set_exposure_time(exposure_time * 1e6) # type: ignore[union-attr]
128
+ await self.comm.set_state(IExposureTime, ExposureTimeState(exposure_time=exposure_time))
160
129
 
161
130
 
162
131
  __all__ = ["AravisCamera"]
@@ -0,0 +1,39 @@
1
+ [project]
2
+ name = "pyobs-aravis"
3
+ version = "2.0.0.dev2"
4
+ description = "pyobs module for Aravis cameras"
5
+ authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
+ requires-python = ">=3.11,<3.14"
7
+ license = "MIT"
8
+ dependencies = [
9
+ "numpy>=2.2.5,<3",
10
+ "pyobs-core>=2.0.0.dev1,<3",
11
+ ]
12
+
13
+ [dependency-groups]
14
+ dev = [
15
+ "black>=25.1.0,<26",
16
+ "ruff>=0.9.0",
17
+ "pyrefly>=1.1.1",
18
+ "pre-commit>=4.2.0,<5",
19
+ ]
20
+
21
+ [build-system]
22
+ requires = ["hatchling"]
23
+ build-backend = "hatchling.build"
24
+
25
+ [tool.black]
26
+ line-length = 120
27
+ target-version = ['py311']
28
+
29
+ [tool.ruff]
30
+ target-version = "py311"
31
+ line-length = 120
32
+
33
+ [tool.ruff.lint]
34
+ select = ["E", "F", "W", "I", "UP", "G"]
35
+ exclude = ["pyobs_aravis/aravis.py"]
36
+
37
+ [tool.pyrefly]
38
+ python-version = "3.11"
39
+ project-excludes = ["pyobs_aravis/aravis.py"]