ephys-link 2.2.1__py3-none-any.whl → 2.3.3__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.2.1"
1
+ __version__ = "2.3.3"
@@ -6,7 +6,7 @@ Instantiates the appropriate bindings based on the platform type and uses them t
6
6
  Usage:
7
7
  Instantiate PlatformHandler with the platform type and call the desired command.
8
8
  """
9
-
9
+ import asyncio
10
10
  from typing import final
11
11
 
12
12
  from vbl_aquarium.models.ephys_link import (
@@ -229,6 +229,44 @@ class PlatformHandler:
229
229
  else:
230
230
  self._inside_brain.discard(request.manipulator_id)
231
231
  return BooleanStateResponse(state=request.inside)
232
+
233
+ async def jackhammer(
234
+ self,
235
+ manipulator_id: str,
236
+ axis: int,
237
+ iterations: int,
238
+ phase1_steps: int,
239
+ phase1_pulses: int,
240
+ phase2_steps: int,
241
+ phase2_pulses: int,
242
+ ) -> PositionalResponse:
243
+ """Perform jackhammer motion to break through dura.
244
+
245
+ Args:
246
+ manipulator_id: Manipulator ID.
247
+ axis: Axis to move (0=X, 1=Y, 2=Z, 3=W/Depth).
248
+ iterations: Number of jackhammer cycles.
249
+ phase1_steps: Number of steps in phase 1.
250
+ phase1_pulses: Pulse count for phase 1.
251
+ phase2_steps: Number of steps in phase 2.
252
+ phase2_pulses: Pulse count for phase 2.
253
+
254
+ Returns:
255
+ Final position of the manipulator after jackhammer and an error message if any.
256
+ """
257
+ try:
258
+ await self._bindings.jackhammer(
259
+ manipulator_id, axis, iterations, phase1_steps, phase1_pulses, phase2_steps, phase2_pulses
260
+ )
261
+ await asyncio.sleep(2) # wait for movement to settle
262
+ final_position = self._bindings.platform_space_to_unified_space(
263
+ await self._bindings.get_position(manipulator_id)
264
+ )
265
+ except Exception as e: # noqa: BLE001
266
+ self._console.exception_error_print("Jackhammer", e)
267
+ return PositionalResponse(error=self._console.pretty_exception(e))
268
+ else:
269
+ return PositionalResponse(position=final_position)
232
270
 
233
271
  async def stop(self, manipulator_id: str) -> str:
234
272
  """Stop a manipulator.
@@ -242,6 +242,24 @@ class Server:
242
242
  return await self._run_if_data_parses(
243
243
  self._platform_handler.set_inside_brain, SetInsideBrainRequest, event, data
244
244
  )
245
+ case "jackhammer":
246
+ if data:
247
+ try:
248
+ parsed = loads(str(data))
249
+ return (
250
+ await self._platform_handler.jackhammer(
251
+ manipulator_id=parsed.get("manipulator_id", parsed.get("ManipulatorId", "")),
252
+ axis=parsed.get("axis", parsed.get("Axis", 3)),
253
+ iterations=parsed.get("iterations", parsed.get("Iterations", 10)),
254
+ phase1_steps=parsed.get("phase1_steps", parsed.get("Phase1Steps", 10)),
255
+ phase1_pulses=parsed.get("phase1_pulses", parsed.get("Phase1Pulses", 15)),
256
+ phase2_steps=parsed.get("phase2_steps", parsed.get("Phase2Steps", 5)),
257
+ phase2_pulses=parsed.get("phase2_pulses", parsed.get("Phase2Pulses", -15)),
258
+ )
259
+ ).to_json_string()
260
+ except JSONDecodeError:
261
+ return self._malformed_request_response(event, data)
262
+ return self._malformed_request_response(event, data)
245
263
  case "stop":
246
264
  if data:
247
265
  return await self._platform_handler.stop(str(data)) # pyright: ignore[reportAny]
@@ -206,6 +206,7 @@ class MPMBinding(BaseBinding):
206
206
  # Keep track of the previous depth to check if the manipulator stopped advancing unexpectedly.
207
207
  current_depth = (await self.get_position(manipulator_id)).w
208
208
  previous_depth = current_depth
209
+ depth = self.get_dimensions().w - depth
209
210
  unchanged_counter = 0
210
211
 
211
212
  # Send move request.
@@ -244,7 +245,7 @@ class MPMBinding(BaseBinding):
244
245
  self._movement_stopped = False
245
246
 
246
247
  # Return the final depth.
247
- return float((await self.get_position(manipulator_id)).w)
248
+ return float(self.get_dimensions().w - (await self.get_position(manipulator_id)).w)
248
249
 
249
250
  @override
250
251
  async def stop(self, manipulator_id: str) -> None:
@@ -10,6 +10,7 @@ from sensapex import UMP, SensapexDevice # pyright: ignore [reportMissingTypeSt
10
10
  from vbl_aquarium.models.unity import Vector4
11
11
 
12
12
  from ephys_link.utils.base_binding import BaseBinding
13
+ from ctypes import c_char, c_int
13
14
  from ephys_link.utils.converters import (
14
15
  list_to_vector4,
15
16
  scalar_mm_to_um,
@@ -144,6 +145,28 @@ class UmpBinding(BaseBinding):
144
145
  async def stop(self, manipulator_id: str) -> None:
145
146
  self._get_device(manipulator_id).stop() # pyright: ignore [reportUnknownMemberType]
146
147
 
148
+ @override
149
+ async def jackhammer(
150
+ self,
151
+ manipulator_id: str,
152
+ axis: int,
153
+ iterations: int,
154
+ phase1_steps: int,
155
+ phase1_pulses: int,
156
+ phase2_steps: int,
157
+ phase2_pulses: int,
158
+ ) -> None:
159
+ self._ump.call(
160
+ "um_take_jackhammer_step",
161
+ c_int(int(manipulator_id)),
162
+ c_char(axis),
163
+ c_int(iterations),
164
+ c_int(phase1_steps),
165
+ c_int(phase1_pulses),
166
+ c_int(phase2_steps),
167
+ c_int(phase2_pulses),
168
+ )
169
+
147
170
  @override
148
171
  def platform_space_to_unified_space(self, platform_space: Vector4) -> Vector4:
149
172
  """
@@ -147,6 +147,31 @@ class BaseBinding(ABC):
147
147
  manipulator_id: Manipulator ID.
148
148
  """
149
149
 
150
+
151
+ async def jackhammer(
152
+ self,
153
+ manipulator_id: str,
154
+ axis: int,
155
+ iterations: int,
156
+ phase1_steps: int,
157
+ phase1_pulses: int,
158
+ phase2_steps: int,
159
+ phase2_pulses: int,
160
+ ) -> None:
161
+ """Perform jackhammer motion to break through dura.
162
+
163
+ Args:
164
+ manipulator_id: Manipulator ID.
165
+ axis: Axis to move (0=X, 1=Y, 2=Z, 3=W/Depth).
166
+ iterations: Number of jackhammer cycles.
167
+ phase1_steps: Number of steps in phase 1.
168
+ phase1_pulses: Pulse count for phase 1 (positive=forward).
169
+ phase2_steps: Number of steps in phase 2.
170
+ phase2_pulses: Pulse count for phase 2 (negative=backward).
171
+ """
172
+ error_message = f"{self.get_display_name()} does not support jackhammer mode"
173
+ raise NotImplementedError(error_message)
174
+
150
175
  @abstractmethod
151
176
  def platform_space_to_unified_space(self, platform_space: Vector4) -> Vector4:
152
177
  """Convert platform space coordinates to unified space coordinates.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ephys-link
3
- Version: 2.2.1
3
+ Version: 2.3.3
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
@@ -27,7 +27,7 @@ Requires-Dist: keyboard==0.13.5
27
27
  Requires-Dist: packaging==25.0
28
28
  Requires-Dist: platformdirs==4.5.1
29
29
  Requires-Dist: pyserial==3.5
30
- Requires-Dist: python-socketio==5.15.1
30
+ Requires-Dist: python-socketio==5.16.0
31
31
  Requires-Dist: requests==2.32.5
32
32
  Requires-Dist: rich==14.2.0
33
33
  Requires-Dist: sensapex==1.504.1
@@ -1,25 +1,25 @@
1
- ephys_link/__about__.py,sha256=4dqvKTDgbqeyzbWj6hYiNdzxsI8j1YOKSLM8vF6a0j4,22
1
+ ephys_link/__about__.py,sha256=s0EEVOzZFl_WT6PzFxk9cgtfsNGRuqeXrX3fgGq9Ogs,22
2
2
  ephys_link/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  ephys_link/__main__.py,sha256=54zxQ-fyxC2-LGsTUdtlvib36ZZQwNyOa6IuffYLhhs,1582
4
4
  ephys_link/back_end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- ephys_link/back_end/platform_handler.py,sha256=6Lt_jaIcO9jTmWYOoWYkuhwSlCTT1Qfd53ru31X0fmc,10130
6
- ephys_link/back_end/server.py,sha256=ILrYbd4r_4GiRmdUEmGcbT1AEIo_TF3i-BZpdhYm8g8,9296
5
+ ephys_link/back_end/platform_handler.py,sha256=CVNb_bU2j4BKGCFMWXO9MeXwRh9lqgmnZ-BeTRqdBFk,11636
6
+ ephys_link/back_end/server.py,sha256=PNGcYng5B4KaKF3PtThugE1zSXTWd9PTWeZQvg34eAY,10503
7
7
  ephys_link/bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  ephys_link/bindings/fake_binding.py,sha256=PI7zYv-SjWsGFEs_FVu5Z5l9gykIqG3C7pQISdbwdoY,2357
9
- ephys_link/bindings/mpm_binding.py,sha256=vn7IKqdiZ6_MX91zomqDXX08ONHwVVgWncRuJTxJpOM,10872
9
+ ephys_link/bindings/mpm_binding.py,sha256=eUm7ELFvbJzwUaUkpqEsPtMuye2iiRGJ-drcI1Ycl_g,10946
10
10
  ephys_link/bindings/parallax_binding.py,sha256=QzZ4MVUc4YGlIxr9__j8I3t3MyGuoQdsZWgHaSedZ3A,10129
11
- ephys_link/bindings/ump_binding.py,sha256=X71n5P3IPlWmQ2BaHUI-UHu-RP__ZOgA3w32iT3169U,7910
11
+ ephys_link/bindings/ump_binding.py,sha256=tvsWLh4bke7-B7AlwdlkmMcVedCr91Nw0otQtcaA3hk,8500
12
12
  ephys_link/front_end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  ephys_link/front_end/cli.py,sha256=vbJYFoaOwPwQq3ShR60HgPQnE-hK6kp1_9FEFkyZ6AU,2899
14
14
  ephys_link/front_end/console.py,sha256=zq67dn7T4xKMg3jjbNra_1s0N9ItvsTRXVIhClWbjP8,3912
15
15
  ephys_link/front_end/gui.py,sha256=MagojumetQGp7e8sK53cI_TgcqKSx54jLNeZagBjNJY,6383
16
16
  ephys_link/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- ephys_link/utils/base_binding.py,sha256=rq0FtvkjAN287nX8rZwR-j6YPzV3Pkp8PqJfZlhIzqo,5413
17
+ ephys_link/utils/base_binding.py,sha256=mVy1kNbVz87asY5VLvVXFD-rbm_uB6EXeL5M8vmLp0A,6282
18
18
  ephys_link/utils/constants.py,sha256=l1-KmGFzAgaBzEIgtmFLfpijum75_1JMdSq5GyR3TJk,3756
19
19
  ephys_link/utils/converters.py,sha256=ZdVmIX-LHCwM__F0SpjN_mfNGGetr1U97xvHd0hf8T0,2038
20
20
  ephys_link/utils/startup.py,sha256=lK04UffvdcASpmp8Arecfmm1dDhzZnZy2rgzQ8sqWag,3971
21
- ephys_link-2.2.1.dist-info/METADATA,sha256=nHO5FaFAmKoqwYbH2gHOvPh-e8-AgyA7TqFoN9zLokM,4707
22
- ephys_link-2.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
23
- ephys_link-2.2.1.dist-info/entry_points.txt,sha256=o8wV3AdnJ9o47vg9ymKxPNVq9pMdPq8UZHE_iyAJx-k,124
24
- ephys_link-2.2.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
25
- ephys_link-2.2.1.dist-info/RECORD,,
21
+ ephys_link-2.3.3.dist-info/METADATA,sha256=ZXg-ues2Tfzy4YUMV25sx__NptdpyCQI1oHESYizTxw,4707
22
+ ephys_link-2.3.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
23
+ ephys_link-2.3.3.dist-info/entry_points.txt,sha256=o8wV3AdnJ9o47vg9ymKxPNVq9pMdPq8UZHE_iyAJx-k,124
24
+ ephys_link-2.3.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
25
+ ephys_link-2.3.3.dist-info/RECORD,,