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.
- pyobs_aravis-2.0.0.dev2/.github/workflows/ruff.yml +26 -0
- pyobs_aravis-2.0.0.dev2/.pre-commit-config.yaml +10 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/PKG-INFO +4 -5
- pyobs_aravis-2.0.0.dev2/README.md +50 -0
- pyobs_aravis-2.0.0.dev2/pyobs_aravis/__init__.py +3 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/pyobs_aravis/araviscamera.py +35 -66
- pyobs_aravis-2.0.0.dev2/pyproject.toml +39 -0
- pyobs_aravis-2.0.0.dev2/uv.lock +1998 -0
- pyobs_aravis-1.1.3/.pre-commit-config.yaml +0 -15
- pyobs_aravis-1.1.3/README.md +0 -28
- pyobs_aravis-1.1.3/pyobs_aravis/__init__.py +0 -4
- pyobs_aravis-1.1.3/pyproject.toml +0 -28
- pyobs_aravis-1.1.3/uv.lock +0 -1167
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/.github/workflows/pypi.yml +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/.readthedocs.yml +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/CHANGELOG.rst +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/LICENSE +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/docs/Makefile +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/docs/make.bat +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/docs/source/_static/pyobs.gif +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/docs/source/conf.py +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/docs/source/index.rst +0 -0
- {pyobs_aravis-1.1.3 → pyobs_aravis-2.0.0.dev2}/pyobs_aravis/aravis.py +0 -0
|
@@ -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/
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyobs-aravis
|
|
3
|
-
Version:
|
|
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:
|
|
9
|
-
Requires-Dist: numpy
|
|
10
|
-
Requires-Dist:
|
|
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).
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
import time
|
|
4
|
-
|
|
5
|
-
from typing import Any, Dict, Optional, List
|
|
4
|
+
from typing import Any
|
|
6
5
|
|
|
7
|
-
|
|
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:
|
|
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:
|
|
37
|
-
self._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
|
-
|
|
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(
|
|
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
|
-
#
|
|
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
|
-
"""
|
|
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
|
-
"""
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
124
|
-
break
|
|
108
|
+
frame = self._camera.pop_frame() # type: ignore[union-attr]
|
|
125
109
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
continue
|
|
110
|
+
if time.time() - last < self._interval:
|
|
111
|
+
await asyncio.sleep(0.01)
|
|
112
|
+
continue
|
|
130
113
|
|
|
131
|
-
|
|
132
|
-
|
|
114
|
+
last = time.time()
|
|
115
|
+
await self._set_image(frame)
|
|
133
116
|
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
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"]
|