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.
- 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.4 → 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.4 → pyobs_aravis-2.0.0.dev2}/pyobs_aravis/araviscamera.py +24 -58
- pyobs_aravis-2.0.0.dev2/pyproject.toml +39 -0
- pyobs_aravis-2.0.0.dev2/uv.lock +1998 -0
- pyobs_aravis-1.1.4/.pre-commit-config.yaml +0 -15
- pyobs_aravis-1.1.4/README.md +0 -28
- pyobs_aravis-1.1.4/pyobs_aravis/__init__.py +0 -4
- pyobs_aravis-1.1.4/pyproject.toml +0 -28
- pyobs_aravis-1.1.4/uv.lock +0 -1180
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/.github/workflows/pypi.yml +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/.readthedocs.yml +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/CHANGELOG.rst +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/LICENSE +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/docs/Makefile +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/docs/make.bat +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/docs/source/_static/pyobs.gif +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/docs/source/conf.py +0 -0
- {pyobs_aravis-1.1.4 → pyobs_aravis-2.0.0.dev2}/docs/source/index.rst +0 -0
- {pyobs_aravis-1.1.4 → 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,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
|
-
|
|
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(
|
|
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
|
-
#
|
|
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
|
-
"""
|
|
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
|
-
"""
|
|
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
|
-
#
|
|
118
|
-
while
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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"]
|