Skip to content

Commit

Permalink
258 unregistering manipulators existential error (#359)
Browse files Browse the repository at this point in the history
* Reset with new CLI parser

* Start main

* CLI

* GUI

* Create base commands

* Color print error

* Make console global

* Get positions

* Move ABC to util, made helper for exception printing

* Implemented the rest except for movement

* Implement set_position?

* Implement depth

* Create platform type getter

* uMp-4 bindings

* Fix try-except styling, instantiate PlatformHandler

* Moved console instance to common, prep for fake platform binding

* Remove call to super in Bindings init (there is no super init)

* Fake manipulator bindings

* Fixed Ruff errors, started server

* Connection and disconnection

* Use global console

* Import console only when available

* Get binaries in, need to find solution to global console

* Fix console and other IDE issues

* Started implementing commands

* Helper validation functions (types aren't checking right)

* Launch, need to change catch all handler

* Fixed catch all, need to test

* Test movement

* Fix match platform typing

* Add type checking to CI

* Switch to static port 3000

* Verify async request handling

* Repeated prints, will be replaced with rich later

* Add debug checkmark to GUI

* Version bump

* Fixed ump-4 position reporting

* Verify stop

* Version bump to beta

* Auto format code

* Static analysis fix

---------

Co-authored-by: kjy5 <[email protected]>
  • Loading branch information
kjy5 and kjy5 authored Jul 5, 2024
1 parent c745e3b commit 282e3da
Show file tree
Hide file tree
Showing 35 changed files with 1,305 additions and 2,674 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/autoformat-and-lint.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Autoformat and Lint
name: Auto Format and Lint

on:
pull_request:
Expand All @@ -9,7 +9,7 @@ on:

jobs:
autoformat-and-lint:
name: Autoformat and Lint
name: Auto Format and Lint
if: github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
Expand Down Expand Up @@ -37,9 +37,12 @@ jobs:
- name: ✅ Commit code format changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Autoformat code"
commit_message: "Auto format code"
skip_fetch: true
skip_checkout: true

- name: 🔍 Lint
run: hatch fmt --check
- name: 🧶 Lint
run: hatch fmt --check

- name: 🔍 Type Check
run: hatch -e types run check
36 changes: 0 additions & 36 deletions .github/workflows/build.yml.off

This file was deleted.

5 changes: 5 additions & 0 deletions ephys_link.spec
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ options = parser.parse_args()

FILE_NAME = f"EphysLink-v{version}"

# noinspection PyUnresolvedReferences
a = Analysis(
['src\\ephys_link\\__main__.py'],
pathex=[],
Expand All @@ -23,9 +24,11 @@ a = Analysis(
noarchive=False,
optimize=1,
)
# noinspection PyUnresolvedReferences
pyz = PYZ(a.pure)

if options.dir:
# noinspection PyUnresolvedReferences
exe = EXE(
pyz,
a.scripts,
Expand All @@ -45,8 +48,10 @@ if options.dir:
entitlements_file=None,
icon='assets\\icon.ico',
)
# noinspection PyUnresolvedReferences
coll = COLLECT(exe, a.binaries, a.datas, strip=False, upx=True, upx_exclude=[], name=FILE_NAME)
else:
# noinspection PyUnresolvedReferences
exe = EXE(
pyz,
a.scripts,
Expand Down
19 changes: 12 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ dependencies = [
"pyserial==3.5",
"python-socketio[asyncio_client]==5.11.3",
"pythonnet==3.0.3",
"requests==2.32.3",
"sensapex==1.400.0",
"vbl-aquarium==0.0.17"
"vbl-aquarium==0.0.18"
]

[project.urls]
Expand All @@ -59,7 +60,6 @@ exclude = ["/.github", "/.idea"]
python = "3.12"
dependencies = [
"coverage[toml]>=6.5",
"mypy>=1.0.0",
"pytest",
]
[tool.hatch.envs.default.scripts]
Expand All @@ -73,7 +73,6 @@ cov = [
"test-cov",
"cov-report",
]
types = "mypy --strict --install-types --non-interactive {args:src/ephys_link tests}"

#[[tool.hatch.envs.all.matrix]]
#python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
Expand All @@ -88,6 +87,15 @@ build = "pyinstaller.exe ephys_link.spec -y -- -d && pyinstaller.exe ephys_link.
build_onefile = "pyinstaller.exe ephys_link.spec -y"
build_clean = "pyinstaller.exe ephys_link.spec -y --clean"

[tool.hatch.envs.types]
python = "3.12"
skip-install = true
dependencies = [
"mypy",
]
[tool.hatch.envs.types.scripts]
check = "mypy --strict --install-types --non-interactive --ignore-missing-imports {args:src/ephys_link tests}"

[tool.coverage.run]
source_pkgs = ["ephys_link", "tests"]
branch = true
Expand All @@ -105,7 +113,4 @@ exclude_lines = [
"no cov",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
]

[tool.ruff.lint]
extend-ignore = ["T201", "PLW0603", "BLE001", "FBT001", "ARG002", "S310"]
]
28 changes: 11 additions & 17 deletions scripts/move_tester.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import json
from asyncio import run

import socketio
from vbl_aquarium.models.ephys_link import GotoPositionRequest
from vbl_aquarium.models.unity import Vector4

if __name__ == "__main__":
sio = socketio.Client()
sio.connect("http://localhost:8081")
from ephys_link.back_end.platform_handler import PlatformHandler
from ephys_link.util.console import Console

sio.emit("register_manipulator", "6")
sio.emit("bypass_calibration", "6")
sio.emit("set_can_write", json.dumps({"manipulator_id": "6", "can_write": True, "hours": 0}))
c = Console(enable_debug=True)
p = PlatformHandler("ump-4", c)
target = Vector4()
# target = Vector4(x=10, y=10, z=10, w=10)

end = ""
while end == "":
sio.emit("goto_pos", json.dumps({"manipulator_id": "6", "pos": [0, 10, 10, 10], "speed": 0.5}))

input("Press enter to continue...")

sio.emit("goto_pos", json.dumps({"manipulator_id": "6", "pos": [10, 10, 10, 10], "speed": 1}))

end = input("Press enter to continue (or type any key then enter to end)...")
print(run(p.set_position(GotoPositionRequest(manipulator_id="6", position=target, speed=5))).to_string())
print("Done!")
24 changes: 0 additions & 24 deletions scripts/proxy_dev.py

This file was deleted.

23 changes: 23 additions & 0 deletions scripts/server_tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from time import sleep

from socketio import SimpleClient
from vbl_aquarium.models.ephys_link import DriveToDepthRequest, InsideBrainRequest
from vbl_aquarium.models.unity import Vector4

with SimpleClient() as sio:
sio.connect("http://localhost:3000")

print(sio.call("set_inside_brain", InsideBrainRequest(manipulator_id="6", inside=True).to_string()))

target = Vector4()
# target = Vector4(x=10, y=10, z=10, w=10)

sio.emit(
"set_depth",
DriveToDepthRequest(manipulator_id="6", depth=10, speed=3).to_string(),
)
sleep(1)
print(sio.call("stop"))
# while True:
# print(sio.call("get_position", "6"))
sio.disconnect()
2 changes: 1 addition & 1 deletion src/ephys_link/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.3.3"
__version__ = "2.0.0b0"
118 changes: 28 additions & 90 deletions src/ephys_link/__main__.py
Original file line number Diff line number Diff line change
@@ -1,104 +1,42 @@
from argparse import ArgumentParser
from asyncio import run
from sys import argv
"""Ephys Link entry point.
Responsible for gathering launch options, instantiating the appropriate interface, and starting the application.
from ephys_link import common as com
from ephys_link.__about__ import __version__ as version
from ephys_link.emergency_stop import EmergencyStop
from ephys_link.gui import GUI
from ephys_link.server import Server
Usage: call main() to start.
"""

from sys import argv

# Setup argument parser.
parser = ArgumentParser(
description="Electrophysiology Manipulator Link: a websocket interface for"
" manipulators in electrophysiology experiments.",
prog="python -m ephys-link",
)
parser.add_argument("-b", "--background", dest="background", action="store_true", help="Skip configuration window.")
parser.add_argument(
"-i", "--ignore-updates", dest="ignore_updates", action="store_true", help="Skip (ignore) checking for updates."
)
parser.add_argument(
"-t",
"--type",
type=str,
dest="type",
default="sensapex",
help='Manipulator type (i.e. "sensapex", "new_scale", or "new_scale_pathfinder"). Default: "sensapex".',
)
parser.add_argument("-d", "--debug", dest="debug", action="store_true", help="Enable debug mode.")
parser.add_argument("-x", "--use-proxy", dest="use_proxy", action="store_true", help="Enable proxy mode.")
parser.add_argument(
"-a",
"--proxy-address",
type=str,
default="proxy2.virtualbrainlab.org",
dest="proxy_address",
help="Proxy IP address.",
)
parser.add_argument(
"-p",
"--port",
type=int,
default=8081,
dest="port",
help="TCP/IP port to use. Default: 8081 (avoids conflict with other HTTP servers).",
)
parser.add_argument(
"--pathfinder_port",
type=int,
default=8080,
dest="pathfinder_port",
help="Port New Scale Pathfinder's server is on. Default: 8080.",
)
parser.add_argument(
"-s",
"--serial",
type=str,
default="no-e-stop",
dest="serial",
nargs="?",
help="Emergency stop serial port (i.e. COM3). Default: disables emergency stop.",
)
parser.add_argument(
"-v",
"--version",
action="version",
version=f"Electrophysiology Manipulator Link v{version}",
help="Print version and exit.",
)
from ephys_link.back_end.platform_handler import PlatformHandler
from ephys_link.back_end.server import Server
from ephys_link.front_end.cli import CLI
from ephys_link.front_end.gui import GUI
from ephys_link.util.console import Console


def main() -> None:
"""Main function"""
"""Ephys Link entry point.
# Parse arguments.
args = parser.parse_args()
1. Get options via CLI or GUI.
2. Instantiate the Console and make it globally accessible.
3. Instantiate the Platform Handler with the appropriate platform bindings.
4. Instantiate the Emergency Stop service.
5. Start the server.
"""

# Launch GUI if there are no CLI arguments.
if len(argv) == 1:
gui = GUI()
gui.launch()
return None
# 1. Get options via CLI or GUI (if no CLI options are provided).
options = CLI().parse_args() if len(argv) > 1 else GUI().get_options()

# Otherwise, create Server from CLI.
server = Server()
# 2. Instantiate the Console and make it globally accessible.
console = Console(enable_debug=options.debug)

# Continue with CLI if not.
com.DEBUG = args.debug
# 3. Instantiate the Platform Handler with the appropriate platform bindings.
platform_handler = PlatformHandler(options.type, console)

# Setup serial port.
if args.serial != "no-e-stop":
e_stop = EmergencyStop(server, args.serial)
e_stop.watch()
# 4. Instantiate the Emergency Stop service.

# Launch with parsed arguments on main thread.
if args.use_proxy:
run(
server.launch_for_proxy(args.proxy_address, args.port, args.type, args.pathfinder_port, args.ignore_updates)
)
else:
server.launch(args.type, args.port, args.pathfinder_port, args.ignore_updates)
# 5. Start the server.
Server(options, platform_handler, console).launch()


if __name__ == "__main__":
Expand Down
Empty file.
Loading

0 comments on commit 282e3da

Please sign in to comment.