{"id":27946670,"url":"https://github.com/oeway/hdscanner-controller","last_synced_at":"2025-06-11T05:06:40.547Z","repository":{"id":286729291,"uuid":"962358304","full_name":"oeway/hdscanner-controller","owner":"oeway","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-08T03:30:13.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-07T13:57:01.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oeway.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-08T03:27:22.000Z","updated_at":"2025-04-08T03:30:17.000Z","dependencies_parsed_at":"2025-04-08T04:36:58.260Z","dependency_job_id":null,"html_url":"https://github.com/oeway/hdscanner-controller","commit_stats":null,"previous_names":["oeway/hdscanner-controller"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oeway%2Fhdscanner-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oeway%2Fhdscanner-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oeway%2Fhdscanner-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oeway%2Fhdscanner-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oeway","download_url":"https://codeload.github.com/oeway/hdscanner-controller/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oeway%2Fhdscanner-controller/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259204809,"owners_count":22821160,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-07T13:56:59.442Z","updated_at":"2025-06-11T05:06:40.509Z","avatar_url":"https://github.com/oeway.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HDScanner Controller API (via Hypha)\n\nThis project exposes an asynchronous controller for the HDScanner scanning software over a [Hypha RPC](https://hypha.io) server.\n\nIt allows you to remotely interact with the scanner using high-level API calls like `snap_image`, `move_stage`, `switch_lens`, etc.\n\n---\n\n## 🚀 Getting Started\n\n### Requirements\n\n- Python 3.8+\n- Dependencies:\n  ```bash\n  pip install numpy imageio hypha-rpc\n  ```\n\n### Run the Scanner Service\n\n```bash\npython scanner_service.py\n```\n\nThis will connect to the HDScanner software on `localhost:58207`, register the service on your Hypha server, and expose public RPC methods.\n\n---\n\n## 🔌 Connecting to the Service via Client\n\nHere is an example client that connects and uses the `snap_image` method:\n\n```python\nimport asyncio\nfrom hypha_rpc import connect_to_server\n\nasync def main():\n    server = await connect_to_server({\"server_url\": \"http://localhost:9527\"})\n\n    # Replace this with the actual service ID you got from the server output\n    svc = await server.get_service(\"your-workspace/your-service-id:hdscanner\")\n\n    # Call the API\n    image = await svc.snap_image()\n    print(\"Image shape:\", image.shape)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n\u003e 📝 You'll see your full service ID when running `scanner_service.py`. It will look like:\n\u003e `workspace-id/service-uid:hdscanner`\n\n---\n\n## 🧠 API Reference\n\n### 📷 `snap_image() → np.ndarray`\nCaptures an image using the scanner camera.\n\n**Returns:**  \n`np.ndarray` — Image as a NumPy array (H, W, C).\n\n---\n\n### 🧪 `get_device_info() → dict`\nReturns scanner device status.\n\n**Returns:**\n```json\n{\n  \"camera\": true,\n  \"controller\": true,\n  \"taskrunning\": false,\n  \"traystep\": 0,\n  \"errorcode\": 0\n}\n```\n\n---\n\n### 🧫 `new_scan(expo_wait=1000) → np.ndarray`\nCreates a new scan session and returns the preview image.\n\n**Arguments:**\n- `expo_wait` (int): Time in milliseconds to wait for exposure stabilization (default: 1000).\n\n**Returns:**  \n`np.ndarray` — Preview image.\n\n---\n\n### 🧭 `move_stage(x=0.0, y=0.0, z=0.0, ack=False) → dict`\nMoves the stage to given coordinates.\n\n**Arguments:**\n- `x`, `y`, `z` (float): Target position in microns.\n- `ack` (bool): Whether to wait for confirmation from the scanner (default: False).\n\n**Returns (if ack=True):**\n```json\n{\n  \"method\": \"StageStopped\",\n  \"result\": 0  # 0 = success, -1 = failure\n}\n```\n\n---\n\n### 🛑 `stop() → dict`\nStops all active tasks (scanning, focusing, moving).\n\n**Returns:**\n```json\n{\n  \"method\": \"ScanStopped\",\n  \"result\": 0  # 0 = success\n}\n```\n\n---\n\n### 📍 `get_stage_info() → dict`\nReturns current stage X/Y/Z position in microns.\n\n**Returns:**\n```json\n{\n  \"X\": 1000.1,\n  \"Y\": 2000.2,\n  \"Z\": 3000.3\n}\n```\n\n---\n\n### 🎛️ `control_stage(mode: str) → dict`\nSends a high-level stage command.\n\n**Arguments:**\n- `mode` (str): One of:\n  - `\"SlideOut\"`, `\"SlideIn\"`, `\"SlidePrev\"`, `\"SlideNext\"`\n  - `\"StageLeft\"`, `\"StageRight\"`, `\"StageOut\"`, `\"StageIn\"`\n  - `\"SlideDown\"`, `\"StageUp\"`, `\"StageHome\"`\n\n**Returns:**  \nCommand acknowledgment.\n\n---\n\n### 🔬 `switch_lens(mag: str) → dict`\nSwitches to a specific objective lens.\n\n**Arguments:**\n- `mag` (str): Magnification label, e.g. `\"20X\"`\n\n**Returns:**  \nConfirmation of lens switch.\n\n---\n\n### 📡 `focus_lens(mode=\"Fast\") → dict`\nFocuses the current objective lens.\n\n**Arguments:**\n- `mode` (str): `\"Fast\"`, `\"Auto\"`, or `\"Manual\"`.\n\n**Returns:**\n```json\n{\n  \"method\": \"FocusStopped\",\n  \"result\": 0  # 0 = success, -1 = failure\n}\n```\n\n---\n\n## 🧩 Notes\n\n- All image functions return NumPy arrays. You can directly visualize them with `matplotlib` or save them with `imageio.imwrite(...)`.\n- Make sure HDScanner software is running with socket communication enabled (`localhost:58207`).\n\n---\n\n## 📬 Support\n\nFor bug reports or feature requests, open an issue or contact Wei Ouyang at [AICell Lab](https://aicell.io).\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foeway%2Fhdscanner-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foeway%2Fhdscanner-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foeway%2Fhdscanner-controller/lists"}