ephys-link 2.0.0b10__py3-none-any.whl → 2.0.2__py3-none-any.whl
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.
- ephys_link/__about__.py +1 -1
- ephys_link/bindings/fake_binding.py +2 -1
- ephys_link/bindings/mpm_binding.py +17 -11
- ephys_link/bindings/ump_4_binding.py +3 -2
- ephys_link/utils/base_binding.py +2 -1
- {ephys_link-2.0.0b10.dist-info → ephys_link-2.0.2.dist-info}/METADATA +19 -21
- {ephys_link-2.0.0b10.dist-info → ephys_link-2.0.2.dist-info}/RECORD +10 -10
- {ephys_link-2.0.0b10.dist-info → ephys_link-2.0.2.dist-info}/WHEEL +0 -0
- {ephys_link-2.0.0b10.dist-info → ephys_link-2.0.2.dist-info}/entry_points.txt +0 -0
- {ephys_link-2.0.0b10.dist-info → ephys_link-2.0.2.dist-info}/licenses/LICENSE +0 -0
ephys_link/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.0.
|
|
1
|
+
__version__ = "2.0.2"
|
|
@@ -57,8 +57,9 @@ class FakeBinding(BaseBinding):
|
|
|
57
57
|
async def get_shank_count(self, manipulator_id: str) -> int:
|
|
58
58
|
return 1
|
|
59
59
|
|
|
60
|
+
@staticmethod
|
|
60
61
|
@override
|
|
61
|
-
def get_movement_tolerance(
|
|
62
|
+
def get_movement_tolerance() -> float:
|
|
62
63
|
return 0.001
|
|
63
64
|
|
|
64
65
|
@override
|
|
@@ -62,12 +62,11 @@ class MPMBinding(BaseBinding):
|
|
|
62
62
|
"AN",
|
|
63
63
|
)
|
|
64
64
|
|
|
65
|
-
# Server
|
|
66
|
-
|
|
65
|
+
# Server data update rate (30 FPS).
|
|
66
|
+
SERVER_DATA_UPDATE_RATE = 1 / 30
|
|
67
67
|
|
|
68
68
|
# Movement polling preferences.
|
|
69
69
|
UNCHANGED_COUNTER_LIMIT = 10
|
|
70
|
-
POLL_INTERVAL = 0.1
|
|
71
70
|
|
|
72
71
|
# Speed preferences (mm/s to use coarse mode).
|
|
73
72
|
COARSE_SPEED_THRESHOLD = 0.1
|
|
@@ -113,7 +112,8 @@ class MPMBinding(BaseBinding):
|
|
|
113
112
|
manipulator_data: dict[str, float] = await self._manipulator_data(manipulator_id)
|
|
114
113
|
stage_z: float = manipulator_data["Stage_Z"]
|
|
115
114
|
|
|
116
|
-
|
|
115
|
+
# Wait for the stage to stabilize.
|
|
116
|
+
await sleep(self.SERVER_DATA_UPDATE_RATE)
|
|
117
117
|
|
|
118
118
|
return Vector4(
|
|
119
119
|
x=manipulator_data["Stage_X"],
|
|
@@ -127,7 +127,7 @@ class MPMBinding(BaseBinding):
|
|
|
127
127
|
manipulator_data: dict[str, float] = await self._manipulator_data(manipulator_id)
|
|
128
128
|
|
|
129
129
|
# Apply PosteriorAngle to Polar to get the correct angle.
|
|
130
|
-
adjusted_polar: int = manipulator_data["Polar"] - (await self._query_data())["PosteriorAngle"]
|
|
130
|
+
adjusted_polar: int = manipulator_data["Polar"] - (await self._query_data())["PosteriorAngle"] # pyright: ignore [reportAny]
|
|
131
131
|
|
|
132
132
|
return Vector3(
|
|
133
133
|
x=adjusted_polar if adjusted_polar > 0 else 360 + adjusted_polar,
|
|
@@ -139,8 +139,9 @@ class MPMBinding(BaseBinding):
|
|
|
139
139
|
async def get_shank_count(self, manipulator_id: str) -> int:
|
|
140
140
|
return int((await self._manipulator_data(manipulator_id))["ShankCount"]) # pyright: ignore [reportAny]
|
|
141
141
|
|
|
142
|
+
@staticmethod
|
|
142
143
|
@override
|
|
143
|
-
def get_movement_tolerance(
|
|
144
|
+
def get_movement_tolerance() -> float:
|
|
144
145
|
return 0.01
|
|
145
146
|
|
|
146
147
|
@override
|
|
@@ -180,7 +181,7 @@ class MPMBinding(BaseBinding):
|
|
|
180
181
|
and unchanged_counter < self.UNCHANGED_COUNTER_LIMIT
|
|
181
182
|
):
|
|
182
183
|
# Wait for a short time before checking again.
|
|
183
|
-
await sleep(self.
|
|
184
|
+
await sleep(self.SERVER_DATA_UPDATE_RATE)
|
|
184
185
|
|
|
185
186
|
# Update current position.
|
|
186
187
|
current_position = await self.get_position(manipulator_id)
|
|
@@ -219,9 +220,13 @@ class MPMBinding(BaseBinding):
|
|
|
219
220
|
)
|
|
220
221
|
|
|
221
222
|
# Wait for the manipulator to reach the target depth or be stopped or get stuck.
|
|
222
|
-
while
|
|
223
|
+
while (
|
|
224
|
+
not self._movement_stopped
|
|
225
|
+
and not abs(current_depth - depth) <= self.get_movement_tolerance()
|
|
226
|
+
and unchanged_counter < self.UNCHANGED_COUNTER_LIMIT
|
|
227
|
+
):
|
|
223
228
|
# Wait for a short time before checking again.
|
|
224
|
-
await sleep(self.
|
|
229
|
+
await sleep(self.SERVER_DATA_UPDATE_RATE)
|
|
225
230
|
|
|
226
231
|
# Get the current depth.
|
|
227
232
|
current_depth = (await self.get_position(manipulator_id)).w
|
|
@@ -281,10 +286,11 @@ class MPMBinding(BaseBinding):
|
|
|
281
286
|
)
|
|
282
287
|
|
|
283
288
|
# Helper functions.
|
|
289
|
+
|
|
284
290
|
async def _query_data(self) -> dict[str, Any]: # pyright: ignore [reportExplicitAny]
|
|
285
291
|
try:
|
|
286
292
|
# Update cache if it's expired.
|
|
287
|
-
if get_running_loop().time() - self.cache_time > self.
|
|
293
|
+
if get_running_loop().time() - self.cache_time > self.SERVER_DATA_UPDATE_RATE:
|
|
288
294
|
# noinspection PyTypeChecker
|
|
289
295
|
self.cache = (await get_running_loop().run_in_executor(None, get, self._url)).json()
|
|
290
296
|
self.cache_time = get_running_loop().time()
|
|
@@ -299,7 +305,7 @@ class MPMBinding(BaseBinding):
|
|
|
299
305
|
return self.cache
|
|
300
306
|
|
|
301
307
|
async def _manipulator_data(self, manipulator_id: str) -> dict[str, Any]: # pyright: ignore [reportExplicitAny]
|
|
302
|
-
probe_data: list[dict[str, Any]] = (await self._query_data())["ProbeArray"] # pyright: ignore [reportExplicitAny]
|
|
308
|
+
probe_data: list[dict[str, Any]] = (await self._query_data())["ProbeArray"] # pyright: ignore [reportExplicitAny, reportAny]
|
|
303
309
|
for probe in probe_data:
|
|
304
310
|
if probe["Id"] == manipulator_id:
|
|
305
311
|
return probe
|
|
@@ -77,8 +77,9 @@ class Ump4Binding(BaseBinding):
|
|
|
77
77
|
error_message = "UMP-4 does not support getting shank count"
|
|
78
78
|
raise AttributeError(error_message)
|
|
79
79
|
|
|
80
|
+
@staticmethod
|
|
80
81
|
@override
|
|
81
|
-
def get_movement_tolerance(
|
|
82
|
+
def get_movement_tolerance() -> float:
|
|
82
83
|
return 0.001
|
|
83
84
|
|
|
84
85
|
@override
|
|
@@ -100,7 +101,7 @@ class Ump4Binding(BaseBinding):
|
|
|
100
101
|
raise RuntimeError(error_message)
|
|
101
102
|
|
|
102
103
|
# Handle empty end position.
|
|
103
|
-
if
|
|
104
|
+
if movement.last_pos is None or len(movement.last_pos) == 0: # pyright: ignore [reportUnknownMemberType, reportUnknownArgumentType]
|
|
104
105
|
error_message = f"Manipulator {manipulator_id} did not reach target position"
|
|
105
106
|
raise RuntimeError(error_message)
|
|
106
107
|
|
ephys_link/utils/base_binding.py
CHANGED
|
@@ -99,8 +99,9 @@ class BaseBinding(ABC):
|
|
|
99
99
|
Number of shanks on the manipulator.
|
|
100
100
|
"""
|
|
101
101
|
|
|
102
|
+
@staticmethod
|
|
102
103
|
@abstractmethod
|
|
103
|
-
def get_movement_tolerance(
|
|
104
|
+
def get_movement_tolerance() -> float:
|
|
104
105
|
"""Get the tolerance for how close the final position must be to the target position in a movement (mm).
|
|
105
106
|
|
|
106
107
|
Returns:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ephys-link
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: A Python Socket.IO server that allows any Socket.IO-compliant application to communicate with manipulators used in electrophysiology experiments.
|
|
5
5
|
Project-URL: Documentation, https://virtualbrainlab.org/ephys_link/installation_and_use.html
|
|
6
6
|
Project-URL: Issues, https://github.com/VirtualBrainLab/ephys-link/issues
|
|
@@ -17,34 +17,31 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
|
17
17
|
Classifier: Operating System :: Microsoft :: Windows
|
|
18
18
|
Classifier: Programming Language :: Python
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
25
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
26
23
|
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
27
|
-
Requires-Python:
|
|
28
|
-
Requires-Dist: aiohttp==3.11.
|
|
24
|
+
Requires-Python: >=3.13
|
|
25
|
+
Requires-Dist: aiohttp==3.11.16
|
|
29
26
|
Requires-Dist: colorama==0.4.6
|
|
30
27
|
Requires-Dist: keyboard==0.13.5
|
|
31
28
|
Requires-Dist: packaging==24.2
|
|
32
|
-
Requires-Dist: platformdirs==4.3.
|
|
29
|
+
Requires-Dist: platformdirs==4.3.7
|
|
33
30
|
Requires-Dist: pyserial==3.5
|
|
34
31
|
Requires-Dist: python-socketio[asyncio-client]==5.12.1
|
|
35
32
|
Requires-Dist: requests==2.32.3
|
|
36
|
-
Requires-Dist: rich==
|
|
33
|
+
Requires-Dist: rich==14.0.0
|
|
37
34
|
Requires-Dist: sensapex==1.400.3
|
|
38
|
-
Requires-Dist: vbl-aquarium==1.0.
|
|
35
|
+
Requires-Dist: vbl-aquarium==1.0.0
|
|
39
36
|
Description-Content-Type: text/markdown
|
|
40
37
|
|
|
41
38
|
# Electrophysiology Manipulator Link
|
|
42
39
|
|
|
43
40
|
[](https://badge.fury.io/py/ephys-link)
|
|
44
|
-
[](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/deploy-docs.yml)
|
|
45
|
-
[](https://pydantic.dev)
|
|
46
41
|
[](https://github.com/pypa/hatch)
|
|
42
|
+
[](https://github.com/astral-sh/uv)
|
|
47
43
|
[](https://github.com/astral-sh/ruff)
|
|
44
|
+
[](https://pydantic.dev)
|
|
48
45
|
[](https://microsoft.github.io/pyright/)
|
|
49
46
|
|
|
50
47
|
<!-- [](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/build.yml) -->
|
|
@@ -59,22 +56,23 @@ to communicate with manipulators used in electrophysiology experiments.
|
|
|
59
56
|
|
|
60
57
|
# Installation
|
|
61
58
|
|
|
62
|
-
##
|
|
59
|
+
## Pinpoint (Recommended)
|
|
63
60
|
|
|
64
61
|
Pinpoint comes bundled with the correct version of Ephys Link. If you are using Pinpoint on the same computer your
|
|
65
|
-
manipulators are connected to, you can launch the server from within Pinpoint.
|
|
66
|
-
|
|
62
|
+
manipulators are connected to, you can launch the server from within Pinpoint. See the documentation
|
|
63
|
+
on [connecting from Pinpoint](../usage/using_ephys_link.md#connecting-to-pinpoint).
|
|
64
|
+
|
|
65
|
+
## Install as a Standalone Executable
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
Download the latest standalone executable or zip from
|
|
68
|
+
the [releases page](https://github.com/VirtualBrainLab/ephys-link/releases/latest).
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
the [releases page](https://github.com/VirtualBrainLab/ephys-link/releases/latest).
|
|
72
|
-
2. Double-click the executable file to start.
|
|
70
|
+
Then see the [usage documentation](../usage/starting_ephys_link.md) for how to run the server.
|
|
73
71
|
|
|
74
72
|
# Documentation and More Information
|
|
75
73
|
|
|
76
|
-
Complete documentation including
|
|
77
|
-
found on
|
|
74
|
+
Complete documentation including how to add manipulators and API usage can be
|
|
75
|
+
found on [Ephys Link's Documentation Website][docs].
|
|
78
76
|
|
|
79
77
|
# Citing
|
|
80
78
|
|
|
@@ -88,4 +86,4 @@ through the issues tab.
|
|
|
88
86
|
|
|
89
87
|
[Pinpoint]: https://github.com/VirtualBrainLab/Pinpoint
|
|
90
88
|
|
|
91
|
-
[docs]: https://
|
|
89
|
+
[docs]: https://ephys-link.virtualbrainlab.org
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
ephys_link/__about__.py,sha256=
|
|
1
|
+
ephys_link/__about__.py,sha256=tATvJM5shAzfspHYjdVwpV2w3-gDA119NlEYi5X2lFY,22
|
|
2
2
|
ephys_link/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
ephys_link/__main__.py,sha256=sbFdC6KJjTfXDgRraU_fmGRPcF4I1Ur9PRDiD86dkRI,1449
|
|
4
4
|
ephys_link/back_end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
ephys_link/back_end/platform_handler.py,sha256=PSlBa2_jM073uaF3MvCd-_a7XXEeTfn5KXJ7aPEwMVk,12149
|
|
6
6
|
ephys_link/back_end/server.py,sha256=mb3K3pXSO-gHaSj1CGJ0v3CSOW5YCi-p0EOKoySRzKQ,10322
|
|
7
7
|
ephys_link/bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
ephys_link/bindings/fake_binding.py,sha256=
|
|
9
|
-
ephys_link/bindings/mpm_binding.py,sha256=
|
|
10
|
-
ephys_link/bindings/ump_4_binding.py,sha256=
|
|
8
|
+
ephys_link/bindings/fake_binding.py,sha256=PI7zYv-SjWsGFEs_FVu5Z5l9gykIqG3C7pQISdbwdoY,2357
|
|
9
|
+
ephys_link/bindings/mpm_binding.py,sha256=vn7IKqdiZ6_MX91zomqDXX08ONHwVVgWncRuJTxJpOM,10872
|
|
10
|
+
ephys_link/bindings/ump_4_binding.py,sha256=NTewhryjJYDDGYXHMiFRICfGBPJqrdStKOMB87dftiY,5421
|
|
11
11
|
ephys_link/front_end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
ephys_link/front_end/cli.py,sha256=isIJs_sZbz7VbNvLgi-HyDlE-TyKD12auDhMTxAkWQU,3099
|
|
13
13
|
ephys_link/front_end/gui.py,sha256=MDcrTS_Xz9bopAgamh4HknqRC10W8E6eOS3Kss_2ZKQ,6864
|
|
14
14
|
ephys_link/resources/libum.dll,sha256=YaD4dwiSNohx-XxHjx2eQWPOBEVvUIXARvx37e_yqNw,316316
|
|
15
15
|
ephys_link/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
ephys_link/utils/base_binding.py,sha256=
|
|
16
|
+
ephys_link/utils/base_binding.py,sha256=rq0FtvkjAN287nX8rZwR-j6YPzV3Pkp8PqJfZlhIzqo,5413
|
|
17
17
|
ephys_link/utils/console.py,sha256=52SYvXv_7Fx8QDL3RMFQoggQ1n5W93Yu5aU7uuJQgfg,3904
|
|
18
18
|
ephys_link/utils/constants.py,sha256=1aML7zBNTM5onVSf6NDrYIR33VJy-dIHd1lFORVBGbM,725
|
|
19
19
|
ephys_link/utils/converters.py,sha256=ZdVmIX-LHCwM__F0SpjN_mfNGGetr1U97xvHd0hf8T0,2038
|
|
20
20
|
ephys_link/utils/startup.py,sha256=jZVed78tuWjUuZqWVgii_zumDr87T-ikEtOFa6KTE_E,2500
|
|
21
|
-
ephys_link-2.0.
|
|
22
|
-
ephys_link-2.0.
|
|
23
|
-
ephys_link-2.0.
|
|
24
|
-
ephys_link-2.0.
|
|
25
|
-
ephys_link-2.0.
|
|
21
|
+
ephys_link-2.0.2.dist-info/METADATA,sha256=goBbmRyz6sCH8A6KRRuIz9Jo2AHT4vkkoRLNcgUvbnA,4607
|
|
22
|
+
ephys_link-2.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
ephys_link-2.0.2.dist-info/entry_points.txt,sha256=o8wV3AdnJ9o47vg9ymKxPNVq9pMdPq8UZHE_iyAJx-k,124
|
|
24
|
+
ephys_link-2.0.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
25
|
+
ephys_link-2.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|