ephys-link 1.0.0rc1__tar.gz → 1.0.6a0__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.
- ephys_link-1.0.6a0/.gitignore +295 -0
- ephys_link-1.0.6a0/PKG-INFO +158 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/README.md +5 -4
- ephys_link-1.0.6a0/pyproject.toml +104 -0
- ephys_link-1.0.6a0/src/ephys_link/__about__.py +1 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/__main__.py +3 -6
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/common.py +22 -19
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/gui.py +20 -37
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platform_handler.py +46 -50
- ephys_link-1.0.6a0/src/ephys_link/platforms/__init__.py +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/new_scale_handler.py +24 -36
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/new_scale_manipulator.py +16 -31
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/new_scale_pathfinder_handler.py +36 -32
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/sensapex_handler.py +26 -39
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/sensapex_manipulator.py +16 -26
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/ump3_handler.py +26 -38
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platforms/ump3_manipulator.py +16 -26
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/server.py +32 -30
- ephys_link-1.0.6a0/tests/__init__.py +3 -0
- ephys-link-1.0.0rc1/MANIFEST.in +0 -1
- ephys-link-1.0.0rc1/PKG-INFO +0 -830
- ephys-link-1.0.0rc1/pyproject.toml +0 -55
- ephys-link-1.0.0rc1/scripts/new_scale_move.py +0 -63
- ephys-link-1.0.0rc1/scripts/probe_crash_test.py +0 -85
- ephys-link-1.0.0rc1/scripts/read_to_file.py +0 -143
- ephys-link-1.0.0rc1/setup.cfg +0 -4
- ephys-link-1.0.0rc1/src/ephys_link.egg-info/SOURCES.txt +0 -35
- ephys-link-1.0.0rc1/tests/__init__.py +0 -1
- ephys-link-1.0.0rc1/tests/calibration_test.py +0 -82
- ephys-link-1.0.0rc1/tests/can_write_test.py +0 -81
- ephys-link-1.0.0rc1/tests/drive_to_depth_test.py +0 -104
- ephys-link-1.0.0rc1/tests/get_manipulators_test.py +0 -32
- ephys-link-1.0.0rc1/tests/get_pos_test.py +0 -48
- ephys-link-1.0.0rc1/tests/inside_brain_test.py +0 -86
- ephys-link-1.0.0rc1/tests/move_test.py +0 -238
- ephys-link-1.0.0rc1/tests/register_manipulator_test.py +0 -47
- ephys-link-1.0.0rc1/tests/stop_test.py +0 -127
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/LICENSE +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/__init__.py +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/platform_manipulator.py +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/resources/CP210xManufacturing.dll +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/resources/NstMotorCtrl.dll +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/resources/SiUSBXp.dll +0 -0
- {ephys-link-1.0.0rc1 → ephys_link-1.0.6a0}/src/ephys_link/resources/libum.dll +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
!libum.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
pip-wheel-metadata/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py,cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
.python-version
|
|
87
|
+
|
|
88
|
+
# pipenv
|
|
89
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
90
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
91
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
92
|
+
# install all needed dependencies.
|
|
93
|
+
#Pipfile.lock
|
|
94
|
+
|
|
95
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
96
|
+
__pypackages__/
|
|
97
|
+
|
|
98
|
+
# Celery stuff
|
|
99
|
+
celerybeat-schedule
|
|
100
|
+
celerybeat.pid
|
|
101
|
+
|
|
102
|
+
# SageMath parsed files
|
|
103
|
+
*.sage.py
|
|
104
|
+
|
|
105
|
+
# Environments
|
|
106
|
+
.env
|
|
107
|
+
.venv
|
|
108
|
+
env/
|
|
109
|
+
venv/
|
|
110
|
+
ENV/
|
|
111
|
+
env.bak/
|
|
112
|
+
venv.bak/
|
|
113
|
+
|
|
114
|
+
# Spyder project settings
|
|
115
|
+
.spyderproject
|
|
116
|
+
.spyproject
|
|
117
|
+
|
|
118
|
+
# Rope project settings
|
|
119
|
+
.ropeproject
|
|
120
|
+
|
|
121
|
+
# mkdocs documentation
|
|
122
|
+
/site
|
|
123
|
+
|
|
124
|
+
# mypy
|
|
125
|
+
.mypy_cache/
|
|
126
|
+
.dmypy.json
|
|
127
|
+
dmypy.json
|
|
128
|
+
|
|
129
|
+
# Pyre type checker
|
|
130
|
+
.pyre/
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# Created by https://www.toptal.com/developers/gitignore/api/python,pycharm
|
|
135
|
+
# Edit at https://www.toptal.com/developers/gitignore?templates=python,pycharm
|
|
136
|
+
|
|
137
|
+
### PyCharm ###
|
|
138
|
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
139
|
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
140
|
+
|
|
141
|
+
# User-specific stuff
|
|
142
|
+
.idea/**/workspace.xml
|
|
143
|
+
.idea/**/tasks.xml
|
|
144
|
+
.idea/**/usage.statistics.xml
|
|
145
|
+
.idea/**/dictionaries
|
|
146
|
+
.idea/**/shelf
|
|
147
|
+
|
|
148
|
+
# AWS User-specific
|
|
149
|
+
.idea/**/aws.xml
|
|
150
|
+
|
|
151
|
+
# Generated files
|
|
152
|
+
.idea/**/contentModel.xml
|
|
153
|
+
|
|
154
|
+
# Sensitive or high-churn files
|
|
155
|
+
.idea/**/dataSources/
|
|
156
|
+
.idea/**/dataSources.ids
|
|
157
|
+
.idea/**/dataSources.local.xml
|
|
158
|
+
.idea/**/sqlDataSources.xml
|
|
159
|
+
.idea/**/dynamic.xml
|
|
160
|
+
.idea/**/uiDesigner.xml
|
|
161
|
+
.idea/**/dbnavigator.xml
|
|
162
|
+
|
|
163
|
+
# Gradle
|
|
164
|
+
.idea/**/gradle.xml
|
|
165
|
+
.idea/**/libraries
|
|
166
|
+
|
|
167
|
+
# Gradle and Maven with auto-import
|
|
168
|
+
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
169
|
+
# since they will be recreated, and may cause churn. Uncomment if using
|
|
170
|
+
# auto-import.
|
|
171
|
+
# .idea/artifacts
|
|
172
|
+
# .idea/compiler.xml
|
|
173
|
+
# .idea/jarRepositories.xml
|
|
174
|
+
# .idea/modules.xml
|
|
175
|
+
# .idea/*.iml
|
|
176
|
+
# .idea/modules
|
|
177
|
+
# *.iml
|
|
178
|
+
# *.ipr
|
|
179
|
+
|
|
180
|
+
# CMake
|
|
181
|
+
cmake-build-*/
|
|
182
|
+
|
|
183
|
+
# Mongo Explorer plugin
|
|
184
|
+
.idea/**/mongoSettings.xml
|
|
185
|
+
|
|
186
|
+
# File-based project format
|
|
187
|
+
*.iws
|
|
188
|
+
|
|
189
|
+
# IntelliJ
|
|
190
|
+
out/
|
|
191
|
+
|
|
192
|
+
# mpeltonen/sbt-idea plugin
|
|
193
|
+
.idea_modules/
|
|
194
|
+
|
|
195
|
+
# JIRA plugin
|
|
196
|
+
atlassian-ide-plugin.xml
|
|
197
|
+
|
|
198
|
+
# Cursive Clojure plugin
|
|
199
|
+
.idea/replstate.xml
|
|
200
|
+
|
|
201
|
+
# SonarLint plugin
|
|
202
|
+
.idea/sonarlint/
|
|
203
|
+
|
|
204
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
205
|
+
com_crashlytics_export_strings.xml
|
|
206
|
+
crashlytics.properties
|
|
207
|
+
crashlytics-build.properties
|
|
208
|
+
fabric.properties
|
|
209
|
+
|
|
210
|
+
# Editor-based Rest Client
|
|
211
|
+
.idea/httpRequests
|
|
212
|
+
|
|
213
|
+
# Android studio 3.1+ serialized cache file
|
|
214
|
+
.idea/caches/build_file_checksums.ser
|
|
215
|
+
|
|
216
|
+
### PyCharm Patch ###
|
|
217
|
+
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
|
218
|
+
|
|
219
|
+
# *.iml
|
|
220
|
+
# modules.xml
|
|
221
|
+
# .idea/misc.xml
|
|
222
|
+
# *.ipr
|
|
223
|
+
|
|
224
|
+
# Sonarlint plugin
|
|
225
|
+
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
|
226
|
+
.idea/**/sonarlint/
|
|
227
|
+
|
|
228
|
+
# SonarQube Plugin
|
|
229
|
+
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
|
230
|
+
.idea/**/sonarIssues.xml
|
|
231
|
+
|
|
232
|
+
# Markdown Navigator plugin
|
|
233
|
+
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
|
234
|
+
.idea/**/markdown-navigator.xml
|
|
235
|
+
.idea/**/markdown-navigator-enh.xml
|
|
236
|
+
.idea/**/markdown-navigator/
|
|
237
|
+
|
|
238
|
+
# Cache file creation bug
|
|
239
|
+
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
|
240
|
+
.idea/$CACHE_FILE$
|
|
241
|
+
|
|
242
|
+
# CodeStream plugin
|
|
243
|
+
# https://plugins.jetbrains.com/plugin/12206-codestream
|
|
244
|
+
.idea/codestream.xml
|
|
245
|
+
|
|
246
|
+
# Azure Toolkit for IntelliJ plugin
|
|
247
|
+
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
|
248
|
+
.idea/**/azureSettings.xml
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
# PyBuilder
|
|
252
|
+
.pybuilder/
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
# pyenv
|
|
256
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
257
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
258
|
+
# .python-version
|
|
259
|
+
|
|
260
|
+
# pipenv
|
|
261
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
262
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
263
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
264
|
+
# install all needed dependencies.
|
|
265
|
+
#Pipfile.lock
|
|
266
|
+
|
|
267
|
+
# poetry
|
|
268
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
269
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
270
|
+
# commonly ignored for libraries.
|
|
271
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
272
|
+
#poetry.lock
|
|
273
|
+
|
|
274
|
+
# pdm
|
|
275
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
276
|
+
#pdm.lock
|
|
277
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
278
|
+
# in version control.
|
|
279
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
280
|
+
.pdm.toml
|
|
281
|
+
|
|
282
|
+
# pytype static type analyzer
|
|
283
|
+
.pytype/
|
|
284
|
+
|
|
285
|
+
# Cython debug symbols
|
|
286
|
+
cython_debug/
|
|
287
|
+
|
|
288
|
+
# PyCharm
|
|
289
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
290
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
291
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
292
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
293
|
+
#.idea/
|
|
294
|
+
|
|
295
|
+
# End of https://www.toptal.com/developers/gitignore/api/python,pycharm
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ephys-link
|
|
3
|
+
Version: 1.0.6a0
|
|
4
|
+
Summary: A Python Socket.IO server that allows any Socket.IO-compliant application to communicate with manipulators used in electrophysiology experiments.
|
|
5
|
+
Project-URL: Documentation, https://virtualbrainlab.org/ephys_link/installation_and_use.html
|
|
6
|
+
Project-URL: Issues, https://github.com/VirtualBrainLab/ephys-link/issues
|
|
7
|
+
Project-URL: Source, https://github.com/VirtualBrainLab/ephys-link
|
|
8
|
+
Author-email: Kenneth Yang <kjy5@uw.edu>
|
|
9
|
+
Maintainer-email: Kenneth Yang <kjy5@uw.edu>
|
|
10
|
+
License-Expression: GPL-3.0-only
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: electrophysiology,ephys,manipulator,neuroscience,neurotech,new-scale,sensapex,socket-io,virtualbrainlab
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
28
|
+
Requires-Python: <3.13,>=3.8
|
|
29
|
+
Requires-Dist: aiohttp==3.9.1
|
|
30
|
+
Requires-Dist: pyserial==3.5
|
|
31
|
+
Requires-Dist: python-socketio==5.10.0
|
|
32
|
+
Requires-Dist: pythonnet==3.0.3
|
|
33
|
+
Requires-Dist: sensapex==1.400.0
|
|
34
|
+
Requires-Dist: wheel==0.42.0
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Electrophysiology Manipulator Link
|
|
38
|
+
|
|
39
|
+
[](https://badge.fury.io/py/ephys-link)
|
|
40
|
+
[](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/codeql-analysis.yml)
|
|
41
|
+
[](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/dependency-review.yml)
|
|
42
|
+
[](https://github.com/pypa/hatch)
|
|
43
|
+
[](https://github.com/astral-sh/ruff)
|
|
44
|
+
|
|
45
|
+
<img width="100%" src="https://github.com/VirtualBrainLab/ephys-link/assets/82800265/c89e433c-2ce0-4f27-aa9d-66f89c59c979" alt="Manipulator and probe in pinpoint moving in sync">
|
|
46
|
+
|
|
47
|
+
The [Electrophysiology Manipulator Link](https://github.com/VirtualBrainLab/ephys-link)
|
|
48
|
+
(or Ephys Link for short) is a Python [Socket.IO](https://socket.io/docs/v4/#what-socketio-is) server that allows any
|
|
49
|
+
Socket.IO-compliant application (such
|
|
50
|
+
as [Pinpoint](https://github.com/VirtualBrainLab/Pinpoint))
|
|
51
|
+
to communicate with manipulators used in electrophysiology experiments.
|
|
52
|
+
|
|
53
|
+
Currently, Ephys Link only supports Sensapex uMp-4 and uMp-3 Micromanipulators and New Scale 3-axis
|
|
54
|
+
manipulators. However, this platform is designed to be extensible to other
|
|
55
|
+
manipulators and more may be added in the future.
|
|
56
|
+
|
|
57
|
+
For more information regarding the server's implementation and how the code is organized, see
|
|
58
|
+
the [package's development documentation](https://virtualbrainlab.org/ephys_link/development.html).
|
|
59
|
+
|
|
60
|
+
For detailed descriptions of the server's API, see
|
|
61
|
+
the [API reference](https://virtualbrainlab.org/api_reference_ephys_link.html).
|
|
62
|
+
|
|
63
|
+
# Installation
|
|
64
|
+
|
|
65
|
+
## Prerequisites
|
|
66
|
+
|
|
67
|
+
1. [Python ≥ 3.8, < 3.13](https://www.python.org/downloads/release/python-3116/)
|
|
68
|
+
1. Python 3.12+ requires the latest version
|
|
69
|
+
of [Microsoft Visual C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) (MSVC v143+) to
|
|
70
|
+
be installed.
|
|
71
|
+
2. An **x86 Windows PC is required** to run the server.
|
|
72
|
+
3. For Sensapex devices, the controller unit must be connected via an ethernet
|
|
73
|
+
cable and powered. A USB-to-ethernet adapter is acceptable. For New Scale manipulators,
|
|
74
|
+
the controller unit must be connected via USB and be powered by a 6V power
|
|
75
|
+
supply.
|
|
76
|
+
4. To use the emergency stop feature, ensure an Arduino with
|
|
77
|
+
the [StopSignal](https://github.com/VirtualBrainLab/StopSignal) sketch is
|
|
78
|
+
connected to the computer. Follow the instructions on that repo for how to
|
|
79
|
+
set up the Arduino.
|
|
80
|
+
|
|
81
|
+
> ### Using a Python virtual environment is encouraged.
|
|
82
|
+
>
|
|
83
|
+
> Create a virtual environment by running `python -m venv ephys_link`
|
|
84
|
+
>
|
|
85
|
+
> Activate the environment by running `.\ephys_link\scripts\activate`
|
|
86
|
+
>
|
|
87
|
+
> A virtual environment helps to isolate installed packages from other packages on your computer and ensures a clean
|
|
88
|
+
> installation of Ephys Link
|
|
89
|
+
|
|
90
|
+
**NOTE:** Ephys Link is an HTTP server without cross-origin support. The server
|
|
91
|
+
is currently designed to interface with local/desktop instances of Pinpoint. It
|
|
92
|
+
will not work with the web browser versions of Pinpoint at this time.
|
|
93
|
+
|
|
94
|
+
## Install for use
|
|
95
|
+
|
|
96
|
+
Run the following command to install the server:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install ephys-link
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Update the server like any other Python package:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install --upgrade ephys-link
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Install for development
|
|
109
|
+
|
|
110
|
+
1. Clone the repository.
|
|
111
|
+
2. Run the following command in the root directory of the repository to install the package along with development
|
|
112
|
+
tools:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install -e .[dev]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
# Usage
|
|
119
|
+
|
|
120
|
+
Run the following commands in a terminal to start the server for the desired manipulator platform:
|
|
121
|
+
|
|
122
|
+
| Manipulator Platform | Command |
|
|
123
|
+
|--------------------------------------|--------------------------------------|
|
|
124
|
+
| Sensapex uMp-4 | `ephys-link` |
|
|
125
|
+
| Sensapex uMp-3 | `ephys-link -t ump3` |
|
|
126
|
+
| New Scale | `ephys-link -t new_scale` |
|
|
127
|
+
| New Scale via Pathfinder HTTP server | `ephys-link -t new_scale_pathfinder` |
|
|
128
|
+
|
|
129
|
+
There are a couple additional aliases for the Ephys Link executable: `ephys_link` and `el`.
|
|
130
|
+
|
|
131
|
+
By default, the server will broadcast with its local IP address on port 8081.
|
|
132
|
+
**Copy this information into Pinpoint to connect**.
|
|
133
|
+
|
|
134
|
+
For example, if the server is running on the same computer that Pinpoint is, use
|
|
135
|
+
|
|
136
|
+
- Server: `localhost`
|
|
137
|
+
- Port: `8081`
|
|
138
|
+
|
|
139
|
+
# Documentation and More Information
|
|
140
|
+
|
|
141
|
+
Complete documentation including API usage and development installation can be
|
|
142
|
+
found on the [Virtual Brain Lab Documentation page][docs] for Ephys Link.
|
|
143
|
+
|
|
144
|
+
# Citing
|
|
145
|
+
|
|
146
|
+
If this project is used as part of a research project you should cite
|
|
147
|
+
the [Pinpoint repository][Pinpoint]. Please email
|
|
148
|
+
Dan ([dbirman@uw.edu](mailto:dbirman@uw.edu)) if you have questions.
|
|
149
|
+
|
|
150
|
+
Please reach out to Kenneth ([kjy5@uw.edu](mailto:kjy5@uw.edu)) for questions
|
|
151
|
+
about the Electrophysiology Manipulator Link server. Bugs may be reported
|
|
152
|
+
through the issues tab.
|
|
153
|
+
|
|
154
|
+
[Pinpoint]: https://github.com/VirtualBrainLab/Pinpoint
|
|
155
|
+
|
|
156
|
+
[StopSignal]: https://github.com/VirtualBrainLab/StopSignal
|
|
157
|
+
|
|
158
|
+
[docs]: https://virtualbrainlab.org/ephys_link/installation_and_use.html
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
[](https://badge.fury.io/py/ephys-link)
|
|
4
4
|
[](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/codeql-analysis.yml)
|
|
5
5
|
[](https://github.com/VirtualBrainLab/ephys-link/actions/workflows/dependency-review.yml)
|
|
6
|
-
[](https://github.com/pypa/hatch)
|
|
7
|
+
[](https://github.com/astral-sh/ruff)
|
|
7
8
|
|
|
8
9
|
<img width="100%" src="https://github.com/VirtualBrainLab/ephys-link/assets/82800265/c89e433c-2ce0-4f27-aa9d-66f89c59c979" alt="Manipulator and probe in pinpoint moving in sync">
|
|
9
10
|
|
|
@@ -13,7 +14,7 @@ Socket.IO-compliant application (such
|
|
|
13
14
|
as [Pinpoint](https://github.com/VirtualBrainLab/Pinpoint))
|
|
14
15
|
to communicate with manipulators used in electrophysiology experiments.
|
|
15
16
|
|
|
16
|
-
Currently, Ephys Link only supports Sensapex uMp-4 Micromanipulators and New Scale 3-axis
|
|
17
|
+
Currently, Ephys Link only supports Sensapex uMp-4 and uMp-3 Micromanipulators and New Scale 3-axis
|
|
17
18
|
manipulators. However, this platform is designed to be extensible to other
|
|
18
19
|
manipulators and more may be added in the future.
|
|
19
20
|
|
|
@@ -84,8 +85,8 @@ Run the following commands in a terminal to start the server for the desired man
|
|
|
84
85
|
|
|
85
86
|
| Manipulator Platform | Command |
|
|
86
87
|
|--------------------------------------|--------------------------------------|
|
|
87
|
-
| Sensapex
|
|
88
|
-
| Sensapex
|
|
88
|
+
| Sensapex uMp-4 | `ephys-link` |
|
|
89
|
+
| Sensapex uMp-3 | `ephys-link -t ump3` |
|
|
89
90
|
| New Scale | `ephys-link -t new_scale` |
|
|
90
91
|
| New Scale via Pathfinder HTTP server | `ephys-link -t new_scale_pathfinder` |
|
|
91
92
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ephys-link"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "A Python Socket.IO server that allows any Socket.IO-compliant application to communicate with manipulators used in electrophysiology experiments."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8, <3.13"
|
|
11
|
+
license = "GPL-3.0-only"
|
|
12
|
+
keywords = ["socket-io", "manipulator", "electrophysiology", "ephys", "sensapex", "neuroscience", "neurotech", "virtualbrainlab", "new-scale"]
|
|
13
|
+
authors = [{ name = "Kenneth Yang", email = "kjy5@uw.edu" }]
|
|
14
|
+
maintainers = [{ name = "Kenneth Yang", email = "kjy5@uw.edu" }]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3.8",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
23
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Intended Audience :: End Users/Desktop",
|
|
28
|
+
"Intended Audience :: Healthcare Industry",
|
|
29
|
+
"Intended Audience :: Science/Research",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Medical Science Apps.",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"aiohttp==3.9.1",
|
|
34
|
+
"pyserial==3.5",
|
|
35
|
+
"python-socketio==5.10.0",
|
|
36
|
+
"pythonnet==3.0.3",
|
|
37
|
+
"wheel==0.42.0",
|
|
38
|
+
"sensapex==1.400.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Documentation = "https://virtualbrainlab.org/ephys_link/installation_and_use.html"
|
|
43
|
+
Issues = "https://github.com/VirtualBrainLab/ephys-link/issues"
|
|
44
|
+
Source = "https://github.com/VirtualBrainLab/ephys-link"
|
|
45
|
+
|
|
46
|
+
[project.scripts]
|
|
47
|
+
ephys-link = "ephys_link.__main__:main"
|
|
48
|
+
ephys_link = "ephys_link.__main__:main"
|
|
49
|
+
el = "ephys_link.__main__:main"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.version]
|
|
52
|
+
path = "src/ephys_link/__about__.py"
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build.targets.sdist]
|
|
55
|
+
exclude = ["/.github", "/.idea"]
|
|
56
|
+
|
|
57
|
+
[tool.hatch.envs.default]
|
|
58
|
+
dependencies = [
|
|
59
|
+
"coverage[toml]>=6.5",
|
|
60
|
+
"pytest",
|
|
61
|
+
]
|
|
62
|
+
[tool.hatch.envs.default.scripts]
|
|
63
|
+
test = "pytest {args:tests}"
|
|
64
|
+
test-cov = "coverage run -m pytest {args:tests}"
|
|
65
|
+
cov-report = [
|
|
66
|
+
"- coverage combine",
|
|
67
|
+
"coverage report",
|
|
68
|
+
]
|
|
69
|
+
cov = [
|
|
70
|
+
"test-cov",
|
|
71
|
+
"cov-report",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[[tool.hatch.envs.all.matrix]]
|
|
75
|
+
python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
|
76
|
+
|
|
77
|
+
[tool.hatch.envs.types]
|
|
78
|
+
dependencies = [
|
|
79
|
+
"mypy>=1.0.0",
|
|
80
|
+
]
|
|
81
|
+
[tool.hatch.envs.types.scripts]
|
|
82
|
+
check = "mypy --install-types --non-interactive {args:src/ephys_link tests}"
|
|
83
|
+
|
|
84
|
+
[tool.coverage.run]
|
|
85
|
+
source_pkgs = ["ephys_link", "tests"]
|
|
86
|
+
branch = true
|
|
87
|
+
parallel = true
|
|
88
|
+
omit = [
|
|
89
|
+
"src/ephys_link/__about__.py",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[tool.coverage.paths]
|
|
93
|
+
ephys_link = ["src/ephys_link", "*/ephys-link/src/ephys_link"]
|
|
94
|
+
tests = ["tests", "*/ephys-link/tests"]
|
|
95
|
+
|
|
96
|
+
[tool.coverage.report]
|
|
97
|
+
exclude_lines = [
|
|
98
|
+
"no cov",
|
|
99
|
+
"if __name__ == .__main__.:",
|
|
100
|
+
"if TYPE_CHECKING:",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint]
|
|
104
|
+
extend-ignore = ["T201", "PLW0603", "BLE001", "FBT001", "ARG002", "S310"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.6a0"
|
|
@@ -69,12 +69,9 @@ parser.add_argument(
|
|
|
69
69
|
type=str,
|
|
70
70
|
dest="type",
|
|
71
71
|
default="sensapex",
|
|
72
|
-
help='Manipulator type (i.e. "sensapex", "new_scale", or "new_scale_pathfinder").'
|
|
73
|
-
' Default: "sensapex"',
|
|
74
|
-
)
|
|
75
|
-
parser.add_argument(
|
|
76
|
-
"-d", "--debug", dest="debug", action="store_true", help="Enable debug mode"
|
|
72
|
+
help='Manipulator type (i.e. "sensapex", "new_scale", or "new_scale_pathfinder").' ' Default: "sensapex"',
|
|
77
73
|
)
|
|
74
|
+
parser.add_argument("-d", "--debug", dest="debug", action="store_true", help="Enable debug mode")
|
|
78
75
|
parser.add_argument(
|
|
79
76
|
"-p",
|
|
80
77
|
"--port",
|
|
@@ -113,7 +110,7 @@ def main() -> None:
|
|
|
113
110
|
|
|
114
111
|
# Parse arguments
|
|
115
112
|
args = parser.parse_args()
|
|
116
|
-
com.
|
|
113
|
+
com.DEBUG = args.debug
|
|
117
114
|
|
|
118
115
|
# Setup serial port
|
|
119
116
|
if args.serial != "no-e-stop":
|
|
@@ -4,23 +4,14 @@ Contains globally used helper functions and typed dictionaries (to be used as
|
|
|
4
4
|
callback parameters)
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
7
9
|
from typing import TypedDict
|
|
8
10
|
|
|
9
11
|
# Debugging flag
|
|
10
12
|
DEBUG = False
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
def set_debug(debug: bool) -> None:
|
|
14
|
-
"""Set debug flag
|
|
15
|
-
|
|
16
|
-
:param debug: True to enable debug mode, False to disable
|
|
17
|
-
:type debug: bool
|
|
18
|
-
:return: None
|
|
19
|
-
"""
|
|
20
|
-
global DEBUG
|
|
21
|
-
DEBUG = debug
|
|
22
|
-
|
|
23
|
-
|
|
24
15
|
def dprint(message: str) -> None:
|
|
25
16
|
"""Print message if debug is enabled
|
|
26
17
|
|
|
@@ -81,11 +72,9 @@ class GetManipulatorsOutputData(dict):
|
|
|
81
72
|
:code:`{"manipulators": ["1", "2"], "error": ""}`
|
|
82
73
|
"""
|
|
83
74
|
|
|
84
|
-
def __init__(
|
|
85
|
-
self, manipulators: list, num_axes: int, dimensions: list, error: str
|
|
86
|
-
) -> None:
|
|
75
|
+
def __init__(self, manipulators: list, num_axes: int, dimensions: list, error: str) -> None:
|
|
87
76
|
"""Constructor"""
|
|
88
|
-
super(
|
|
77
|
+
super().__init__(
|
|
89
78
|
manipulators=manipulators,
|
|
90
79
|
num_axes=num_axes,
|
|
91
80
|
dimensions=dimensions,
|
|
@@ -107,7 +96,7 @@ class PositionalOutputData(dict):
|
|
|
107
96
|
|
|
108
97
|
def __init__(self, position: list, error: str) -> None:
|
|
109
98
|
"""Constructor"""
|
|
110
|
-
super(
|
|
99
|
+
super().__init__(position=position, error=error)
|
|
111
100
|
|
|
112
101
|
|
|
113
102
|
class AngularOutputData(dict):
|
|
@@ -121,7 +110,21 @@ class AngularOutputData(dict):
|
|
|
121
110
|
|
|
122
111
|
def __init__(self, angles: list, error: str) -> None:
|
|
123
112
|
"""Constructor"""
|
|
124
|
-
super(
|
|
113
|
+
super().__init__(angles=angles, error=error)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ShankCountOutputData(dict):
|
|
117
|
+
"""Output format for (num_shanks, error)
|
|
118
|
+
|
|
119
|
+
:param shank_count: Number of shanks on the probe
|
|
120
|
+
:type shank_count: int
|
|
121
|
+
:param error: Error message
|
|
122
|
+
:type error: str
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
def __init__(self, shank_count: int, error: str) -> None:
|
|
126
|
+
"""Constructor"""
|
|
127
|
+
super().__init__(shank_count=shank_count, error=error)
|
|
125
128
|
|
|
126
129
|
|
|
127
130
|
class DriveToDepthOutputData(dict):
|
|
@@ -137,7 +140,7 @@ class DriveToDepthOutputData(dict):
|
|
|
137
140
|
|
|
138
141
|
def __init__(self, depth: float, error: str) -> None:
|
|
139
142
|
"""Create drive to depth output data dictionary"""
|
|
140
|
-
super(
|
|
143
|
+
super().__init__(depth=depth, error=error)
|
|
141
144
|
|
|
142
145
|
|
|
143
146
|
class StateOutputData(dict):
|
|
@@ -153,4 +156,4 @@ class StateOutputData(dict):
|
|
|
153
156
|
|
|
154
157
|
def __init__(self, state: bool, error: str) -> None:
|
|
155
158
|
"""Create state output data dictionary"""
|
|
156
|
-
super(
|
|
159
|
+
super().__init__(state=state, error=error)
|