{"id":15020685,"url":"https://github.com/kzhao1228/pystage_apt","last_synced_at":"2025-10-26T04:31:00.818Z","repository":{"id":44645727,"uuid":"244960643","full_name":"kzhao1228/pystage_apt","owner":"kzhao1228","description":"A python library for Thorlabs' APT stage controllers","archived":false,"fork":false,"pushed_at":"2022-02-02T12:00:25.000Z","size":7672,"stargazers_count":10,"open_issues_count":2,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-09-28T10:22:52.294Z","etag":null,"topics":["actuator","actuator-control","controller","linux","motor-controller","python3","raspberian","raspberry-pi","thorlabs"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kzhao1228.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-04T17:21:06.000Z","updated_at":"2024-07-09T10:27:29.000Z","dependencies_parsed_at":"2022-09-13T15:41:11.200Z","dependency_job_id":null,"html_url":"https://github.com/kzhao1228/pystage_apt","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzhao1228%2Fpystage_apt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzhao1228%2Fpystage_apt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzhao1228%2Fpystage_apt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzhao1228%2Fpystage_apt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kzhao1228","download_url":"https://codeload.github.com/kzhao1228/pystage_apt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219864035,"owners_count":16555943,"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":["actuator","actuator-control","controller","linux","motor-controller","python3","raspberian","raspberry-pi","thorlabs"],"created_at":"2024-09-24T19:55:26.083Z","updated_at":"2025-10-26T04:30:53.356Z","avatar_url":"https://github.com/kzhao1228.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"============\n pyStage-APT\n============\n\n|LANGUAGE| |PY-VERSION| |GITHUB-TAG| |PLATFORM_I| |PLATFORM_II| |SERIAL| |USB| |LICENSE| |COUNTS-TOT| \n\n``pystage-apt`` is a library to communicate with various Thorlabs’ APT single-channel controllers and control different types of Thorlabs’ actuator motors. It contains a large collection of motor control messages obtained from `Thorlabs APT Controllers Host-Controller Communications Protocol \u003chttps://https://github.com/kzhao1228/pystage_apt/blob/master/doc/APT_Communications_Protocol_Rev_15.pdf\u003e`__. This document describes the low-level communications protocol and commands used between the host PC and controller units within the APT family. Those messages are included in a series of python files and are stored in a folder named `ctrl_msg \u003chttps://github.com/kzhao1228/pystage_apt/tree/master/stage/ctrl_msg\u003e`__.\n\nAfter you connect Thorlabs APT controllers (with stages connected) to your PC or a Raspberry Pi through USB ports, type and run the code below in, for example, Terminal, to get the controllers discovered by ``pystage-apt``. \n\n\u003e\u003e\u003e from stage.motor_ini.core import find_stages\n\u003e\u003e\u003e s = list(find_stages())\nSuccess: Stage MTS25-Z8 is detected and a controller with serial number 83845481 is connected via \nport /dev/ttyUSB1\nSuccess: Stage Z812 is detected and a controller with serial number 83844171 is connected via \nport /dev/ttyUSB0\n\nOnce you see the success messages like these, congratulations, the controllers along with the stages are 'constructed' and are ready to be manipulated through recognised commands! Ta-da!\n\n\u003e\u003e\u003e s1 = s[1]\n\u003e\u003e\u003e s2 = s[0]\n\u003e\u003e\u003e s1.status\n\u003e\u003e\u003e s2.status\n\n``pystage-apt`` works on Linux and Raspbian, in any console or in a GUI, and is also friendly with IPython/Jupyter notebooks. \n     \n------------------------------------------\n\n.. contents:: Table of contents\n   :backlinks: top\n   :local:\n\n\nInstallation\n------------\n\nLatest PyPI stable release\n~~~~~~~~~~~~~~~~~~~~~~~~~~     \n\n|PY-VERSION|\n\n.. code:: sh\n\n    pip install pystage-apt\n    \n    \nLatest development release on GitHub\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n|GITHUB-TAG|\n\nPull and install in the current directory:\n\n.. code:: sh\n\n    pip install -e git+https://github.com/kzhao1228/pystage_apt.git@master#egg=pystage_apt\n    \nChangelog\n---------\n\nThe list of all changes is available on GitHub's Releases: |GITHUB-TAG|\n    \nPlatform\n--------\n\n|PLATFORM_I| |PLATFORM_II|\n\n``pystage-apt`` supports computationally constructing Thorlabs APT controllers on Linux and Raspbian. It may work on MacOS too only if you can find a way to create a ``/dev`` entry for raw access to USB devices. Because currently there is no way to access them as ``tty`` devices. For Windows, you can try `thorlabs_apt \u003chttps://github.com/qpit/thorlabs_apt\u003e`__.\n\nNote that, before you try to implement this library, you should first configure the ``/etc/udev/rules.d/99-com.rules`` file to avoid potential access permission error on USB device. To do this, open a Terminal window, type and run the command:\n\n.. code:: sh\n\n     sudo nano /etc/udev/rules.d/99-com.rules\n\nAdding to this file with contents like this:\n\n.. code:: sh\n\n     SUBSYSTEM==\"usb\", ATTR{idVendor}==\"HEX1\", ATTR{idProduct}==\"HEX2\", MODE=\"0666\"\n\nwhere **HEX1** and **HEX2** are replaced with the vendor and product id respectively. For example, this content could be:\n\n.. code:: sh\n\n     SUBSYSTEM==\"usb\", ATTR{idVendor}==\"0403\", ATTR{idProduct}==\"faf0\", MODE=\"0666\"\n     \nHowever, if you don't know the information, you could try typing and running the command ``lsusb`` in Terminal which should give you:\n\n.. code:: sh\n\n     Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub\n     Bus 001 Device 004: ID 0403:faf0 Future Technology Devices International, Ltd \n     Bus 001 Device 003: ID 0403:faf0 Future Technology Devices International, Ltd \n     Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub\n     Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub\n\nwhere ``idVendor:idProduct`` contains the information you need. After finishing editing the file, hit ``Ctrl+O`` to write out and hit ``enter`` to confirm the file name. To exit the file editing mode, simply hit ``Ctrl+X``.\n\n\nAlgorithm\n---------\n\nFunction ``find_stages`` `[1] \u003chttps://github.com/kzhao1228/pystage_apt/blob/310c53fc141731c91ac55acff9fb34c7695f31c1/stage/motor_ini/core.py#L8\u003e`__ scans all connected USB devices and searches for Thorlabs APT controllers. If no controllers are found, function ``list(find_stages())`` returns an empty list. However, if one or more are found, ``list(find_stages())`` returns success messages along with a list of elements in *type* ``stage.motor_ctrl.MotorCtrl``. These elements, which read ``SingleControllerPort('PORT_ENTRY',SERIAL_NO)``, store information as to created serial port entry and controller serial number in the arguments of *Class* ``SingleControllerPort`` `[2] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/port.py#L202\u003e`__ respectively. This *class* contains a *method* named ``get_stages`` that calls *class* ``MotorCtrl`` `[3] \u003chttps://github.com/kzhao1228/pystage_apt/blob/310c53fc141731c91ac55acff9fb34c7695f31c1/stage/motor_ctrl/__init__.py#L9\u003e`__, stores it in a dictionary as a value of a key and returns the dictionary. This value is extracted by functions ``p = Port.create('PORT_ENTRY',SERIAL_NO)`` and ``p.get_stages().values()`` `[4] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/core.py#L45\u003e`__ when ``find_stages`` `[1] \u003chttps://github.com/kzhao1228/pystage_apt/blob/310c53fc141731c91ac55acff9fb34c7695f31c1/stage/motor_ini/core.py#L8\u003e`__ is being implemented.\n\n``Port.create('PORT_ENTRY',SERIAL_NO)`` `[4] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/core.py#L45\u003e`__ calls *method* ``create`` `[5] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/port.py#L183\u003e`__ of *class* ``Port`` `[6] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/port.py#L10\u003e`__ which then calls ``SingleControllerPort`` `[2] \u003chttps://github.com/kzhao1228/pystage_apt/blob/a9579e028c0e7241116439e2998256e0b1a91166/stage/motor_ini/port.py#L202\u003e`__ and returns it. Therefore, ``list(find_stages())`` basically returns a list of callable ``MotorCtrl`` `[3] \u003chttps://github.com/kzhao1228/pystage_apt/blob/310c53fc141731c91ac55acff9fb34c7695f31c1/stage/motor_ctrl/__init__.py#L9\u003e`__, each of which is dependent of a detected stage. Upon calling *instances*, *properties* and *methods* included in ``MotorCtrl`` `[3] \u003chttps://github.com/kzhao1228/pystage_apt/blob/310c53fc141731c91ac55acff9fb34c7695f31c1/stage/motor_ctrl/__init__.py#L9\u003e`__, their corresponding control messages `[5] \u003chttps://github.com/kzhao1228/pystage_apt/tree/master/stage/ctrl_msg\u003e`__ are invoked to structure a series of instructions to be delivered to the controllers and these instructions are decoded to strings of hexadecimal characters that can be understood by the controllers before they are sent out.\n\n \n \nLICENSE\n-------\n\nOpen Source (OSI approved): |LICENSE|\n\n\n\n\n.. |LICENSE| image:: https://img.shields.io/dub/l/vibe-d\n   :target: https://raw.githubusercontent.com/kzhao1228/pystage_apt/master/LICENSE.txt\n   :alt: License\n   \n.. |LANGUAGE| image:: https://img.shields.io/badge/python-v3.2%20|%20v3.3%20|%20v3.4%20|%20v3.5%20|%20v3.6%20|%20v3.7%20|%20v3.8-blue?\u0026logo=python\u0026logoColor=white\n   :target: https://pypi.org/project/pystage-apt/\n   :alt: Language\n\n.. |PLATFORM_I| image:: https://img.shields.io/badge/platform-linux--64-blue?\u0026logo=linux\u0026logoColor=white\n   :target: https://www.linux.org/pages/download/\n   :alt: Platform_i\n   \n.. |PLATFORM_II| image:: https://img.shields.io/badge/platform-raspbian-blue?\u0026logo=Raspberry%20Pi\n   :target: https://www.raspberrypi.org/downloads/raspbian/\n   :alt: Platform_ii\n   \n.. |SERIAL| image:: https://img.shields.io/badge/pyserial-%3E=2.7-important?\u0026logo=koding\u0026logoColor=white\n   :target: https://github.com/pyserial/pyserial\n   :alt: SERIAL\n   \n.. |USB| image:: https://img.shields.io/badge/pyusb-%3E=1.0.0a-important?\u0026logo=koding\u0026logoColor=white\n   :target: https://github.com/pyusb/pyusb\n   :alt: USB\n   \n.. |PY-VERSION| image:: https://img.shields.io/badge/pypi-v0.4-blue?\u0026logo=pypi\u0026logoColor=white\n   :target: https://pypi.org/project/pystage-apt/#history\n   :alt: Py-version\n  \n.. |GITHUB-TAG| image:: https://img.shields.io/badge/tag-%20%20v0.4-blue?\u0026logo=github\n   :target: https://github.com/kzhao1228/pystage_apt/releases\n   :alt: GitHub-tags\n   \n.. |COUNTS-TOT| image:: https://visitor-badge.glitch.me/badge?page_id=kzhao1228.pystage-apt\n   :target: https://github.com/kzhao1228/pystage_apt/blob/master/README.rst\n   :alt: Counts-total\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkzhao1228%2Fpystage_apt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkzhao1228%2Fpystage_apt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkzhao1228%2Fpystage_apt/lists"}