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 CHANGED
@@ -1 +1 @@
1
- __version__ = "2.0.0b10"
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(self) -> float:
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 cache lifetime (60 FPS).
66
- CACHE_LIFETIME = 1 / 60
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
- await sleep(self.POLL_INTERVAL) # Wait for the stage to stabilize.
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(self) -> float:
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.POLL_INTERVAL)
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 not self._movement_stopped and not abs(current_depth - depth) <= self.get_movement_tolerance():
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.POLL_INTERVAL)
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.CACHE_LIFETIME:
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(self) -> float:
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 not movement.last_pos: # pyright: ignore [reportUnknownMemberType]
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
 
@@ -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(self) -> float:
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.0b10
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: <3.14,>=3.10
28
- Requires-Dist: aiohttp==3.11.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.6
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==13.9.4
33
+ Requires-Dist: rich==14.0.0
37
34
  Requires-Dist: sensapex==1.400.3
38
- Requires-Dist: vbl-aquarium==1.0.0b3
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
  [![PyPI version](https://badge.fury.io/py/ephys-link.svg)](https://badge.fury.io/py/ephys-link)
44
- [![Deploy Documentation](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/deploy-docs.yml/badge.svg)](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/deploy-docs.yml)
45
- [![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev)
46
41
  [![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
42
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
47
43
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
44
+ [![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev)
48
45
  [![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
49
46
 
50
47
  <!-- [![Build](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/build.yml/badge.svg)](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
- ## Launch from Pinpoint (Recommended)
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. Follow the instructions in
66
- the [Pinpoint documentation](https://virtualbrainlab.org/pinpoint/tutorials/tutorial_ephys_link.html#configure-and-launch-ephys-link).
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
- ## Install as Standalone Executable
67
+ Download the latest standalone executable or zip from
68
+ the [releases page](https://github.com/VirtualBrainLab/ephys-link/releases/latest).
69
69
 
70
- 1. Download the latest standalone executable or zip from
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 API usage and development installation can be
77
- found on the [Virtual Brain Lab Documentation page][docs] for Ephys Link.
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://virtualbrainlab.github.io/ephys-link/
89
+ [docs]: https://ephys-link.virtualbrainlab.org
@@ -1,25 +1,25 @@
1
- ephys_link/__about__.py,sha256=ZfWxxrYzAnkQgRa0A4sw5HmxwHoGy-NT_dsW092TiYE,25
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=VCmKZha113kiHSmOZzKLfbaa8iXobefJFQPI3eCzuZE,2343
9
- ephys_link/bindings/mpm_binding.py,sha256=UdrWXiz16zJ7PSQBnYNtpTXs_1chbE_v1tvzeP7PrPk,10681
10
- ephys_link/bindings/ump_4_binding.py,sha256=_ZEMT6B4aEqJHdwSElnkOnaXxG7wwKeUgsHZ5T6ekgg,5345
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=9ScaIXLwhAgHP4jLIG5LUf1AYjF_Jmf0nRH606_mXEQ,5399
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.0b10.dist-info/METADATA,sha256=QDm7UqgMT8PiyN2oZATDHfSG3bksexec-rFbNteIKq4,4869
22
- ephys_link-2.0.0b10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- ephys_link-2.0.0b10.dist-info/entry_points.txt,sha256=o8wV3AdnJ9o47vg9ymKxPNVq9pMdPq8UZHE_iyAJx-k,124
24
- ephys_link-2.0.0b10.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
25
- ephys_link-2.0.0b10.dist-info/RECORD,,
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,,