pyobs-aravis 1.1.4__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.4
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,15 +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
54
  raise ValueError("Could not find given device name in list of available cameras.")
58
55
 
59
- # open camera
60
56
  await self.activate_camera()
61
57
 
62
58
  async def close(self) -> None:
@@ -69,72 +65,56 @@ class AravisCamera(BaseVideo, IExposureTime):
69
65
  """Open camera."""
70
66
  from . import aravis
71
67
 
72
- # open camera
73
68
  log.info("Connecting to camera %s...", self._device_name)
74
- self._camera = aravis.Camera(self._device_name) # type: ignore
69
+ self._camera = aravis.Camera(self._device_name) # type: ignore[assignment]
75
70
  log.info("Connected.")
76
71
 
77
- # settings
78
72
  for key, value in self._settings.items():
79
- log.info(f"Setting value {key}={value}...")
80
- 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]
81
75
 
82
- # start acquisition
83
- 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]
84
77
 
85
78
  def _close_camera(self) -> None:
86
79
  """Close camera."""
87
- # stop camera
88
80
  if self._camera is not None:
89
81
  log.info("Closing camera...")
90
- self._camera.stop_acquisition() # type: ignore
91
- self._camera.shutdown() # type: ignore
82
+ self._camera.stop_acquisition() # type: ignore[union-attr]
83
+ self._camera.shutdown() # type: ignore[union-attr]
92
84
  self._camera = None
93
85
 
94
86
  async def _activate_camera(self) -> None:
95
- """Can be overridden by derived class to implement inactivity sleep"""
87
+ """Open camera on activation."""
96
88
  async with self._camera_lock:
97
89
  self._open_camera()
98
90
 
99
91
  async def _deactivate_camera(self) -> None:
100
- """Can be overridden by derived class to implement inactivity sleep"""
92
+ """Close camera on deactivation."""
101
93
  async with self._camera_lock:
102
94
  self._close_camera()
103
95
 
104
96
  async def _capture(self) -> None:
105
97
  """Take new images in loop."""
106
-
107
- # loop until closing
108
98
  last = time.time()
109
99
  while True:
110
100
  try:
111
- # no camera or not active?
112
101
  if self._camera is None or not self.camera_active:
113
- # wait a little
114
102
  await asyncio.sleep(0.1)
115
103
  continue
116
104
 
117
- # read frame
118
- while True:
119
- frame: npt.NDArray[float] = self._camera.pop_frame() # type: ignore
120
- if frame is None:
121
- await asyncio.sleep(0.01)
122
- else:
123
- break
105
+ frame: npt.NDArray[Any] = self._camera.pop_frame() # type: ignore[union-attr]
106
+ while frame is None:
107
+ await asyncio.sleep(0.01)
108
+ frame = self._camera.pop_frame() # type: ignore[union-attr]
124
109
 
125
- # if time since last image is too short, wait a little
126
110
  if time.time() - last < self._interval:
127
111
  await asyncio.sleep(0.01)
128
112
  continue
129
113
 
130
- # save time
131
114
  last = time.time()
132
-
133
- # process it
134
115
  await self._set_image(frame)
135
116
 
136
- except:
137
- # whatever happened here, we don't want the method to die
117
+ except Exception:
138
118
  await asyncio.sleep(1)
139
119
 
140
120
  async def set_exposure_time(self, exposure_time: float, **kwargs: Any) -> None:
@@ -142,24 +122,10 @@ class AravisCamera(BaseVideo, IExposureTime):
142
122
 
143
123
  Args:
144
124
  exposure_time: Exposure time in seconds.
145
-
146
- Raises:
147
- ValueError: If exposure time could not be set.
148
- """
149
- await self.activate_camera()
150
- self._camera.set_exposure_time(exposure_time * 1e6) # type: ignore
151
-
152
- async def get_exposure_time(self, **kwargs: Any) -> float:
153
- """Returns the exposure time in seconds.
154
-
155
- Returns:
156
- Exposure time in seconds.
157
125
  """
158
126
  await self.activate_camera()
159
- return self._camera.get_exposure_time() / 1e6 # type: ignore
160
-
161
- async def get_exposure_time_left(self, **kwargs: Any) -> float:
162
- 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))
163
129
 
164
130
 
165
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"]