{"id":25578973,"url":"https://github.com/l-johnston/autolv","last_synced_at":"2025-04-12T16:37:38.823Z","repository":{"id":38301131,"uuid":"392384415","full_name":"l-johnston/autolv","owner":"l-johnston","description":"Automate LabVIEW from Python","archived":false,"fork":false,"pushed_at":"2023-10-05T10:18:39.000Z","size":510,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-26T11:03:49.436Z","etag":null,"topics":["labview"],"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/l-johnston.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-08-03T16:37:45.000Z","updated_at":"2025-03-17T12:11:44.000Z","dependencies_parsed_at":"2022-09-08T07:34:24.485Z","dependency_job_id":null,"html_url":"https://github.com/l-johnston/autolv","commit_stats":{"total_commits":43,"total_committers":3,"mean_commits":"14.333333333333334","dds":0.2093023255813954,"last_synced_commit":"fc388030aa58cb3dfb2ea1087c242e4c37842a40"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l-johnston%2Fautolv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l-johnston%2Fautolv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l-johnston%2Fautolv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/l-johnston%2Fautolv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/l-johnston","download_url":"https://codeload.github.com/l-johnston/autolv/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248597650,"owners_count":21130916,"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":["labview"],"created_at":"2025-02-21T03:45:16.228Z","updated_at":"2025-04-12T16:37:38.799Z","avatar_url":"https://github.com/l-johnston.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![PyPI](https://img.shields.io/pypi/v/autolv)\n# autolv - Interact with LabVIEW VIs from Python\n\nThe only export from autolv is App that opens an ActiveX connection to\nLabVIEW through its VI Server. With a reference to LabVIEW it is then possible\nto open an ActiveX connection to a specific VI. The primary use case for this\nlibrary is to set control values on the VI front panel from Python, run the VI,\nand read the control values back into Python.\n\nInstallation\n------------\npip install autolv\n\nExample usage\n-------------\nSuppose the VI name is 'test.vi' and has a single Numeric control with the name (label)\n'input' and a single Numeric indicator with the name 'output'. The VI implements\n2*'input' -\u003e 'output'\n\n```python\n\u003e\u003e\u003e import autolv\n\u003e\u003e\u003e lv = autolv.App()\n\u003e\u003e\u003e vi = lv.open('test.vi')\n\u003e\u003e\u003e vi.input = 2.0\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi.output\n4.0\n```\n\nNow move the 'input and 'output' Numeric controls into a Cluster called 'data'.\n\n![test.vi](./doc/_static/testvi.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open('test.vi')\n\u003e\u003e\u003e vi.data.input = 3.0\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi.data.output\n6.0\n```\n\nIt's possible to get an error code explanation. Suppose a VI attempts to create\nan invalid DAQmx channel.\n\n![error.vi](./doc/_static/errorvi.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open('error.vi')\n\u003e\u003e\u003e vi.DAQmx = \"PXI1Slot2\"\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi['error out'].code.value\n-201237\n\u003e\u003e\u003e lv.explain_error(_)\n'Physical channel name specified is invalid...'\n```\n\nIn Jupyter, run the VI in the following way:\n\n```python\nIn [1]: import autolv\nIn [2]: lv = autolv.App()\nIn [3]: vi = lv.open('test.vt')\nIn [4]: vi.input = 2.0\nIn [5]: await vi.run()\nIn [6]: vi.output\nOut[6]: 4.0\n```\n\nAs a context manager:\n\n```python\n\u003e\u003e\u003e with autolv.App() as lv:\n    vi = lv.open(\u003cfile\u003e)\n    ...\n\u003e\u003e\u003e\n```\n\nLabVIEW will close upon exiting the context if it was not running prior to\nentering the context.\n\nVI() and VI.run()\n-----------------\n\nIt is possible to call the VI object directly instead of using VI.run(). Reusing the\n'test.vi' from above where `output`= 2 * `input` and these controls have been wired\nto the connector pane:\n\n```python\n\u003e\u003e\u003e import autolv\n\u003e\u003e\u003e lv = autolv.App()\n\u003e\u003e\u003e vi = lv.open('test.vi')\n\u003e\u003e\u003e vi(input=2.0, output=0.0)\n\u003e\u003e\u003e vi.output\n4.0\n```\n\nThere are two key differences between VI() and VI.run():\n- VI() is blocking where as VI.run() is an asyncio task and supports a timeout.\n- VI() supports reentrant calls where as VI.run() is equivalent to Operate-\u003eRun and\n    does not support reentrant calls.\n\nSpecify a cluster as a dictionary. Suppose 'test.vi' has a cluster `data_in` with\none numeric control `input` and a cluster `data_out` with one numeric indicator `output`\nand `output` = 2 * `input`:\n\n![test.vi](./doc/_static/testvi_clusters.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open('test.vi')\n\u003e\u003e\u003e vi(data_in={\"input\": 3}, data_out={})\n\u003e\u003e\u003e vi.data.output\n6.0\n```\n\nControl labels\n--------------\nIt is recommended to label controls as a valid Python identifier which improves\nproductivity when using dot-access in an interactive session. But, LabVIEW controls\noften are given names that are invalid Python identifiers. It is possible to work\nwith these. Suppose a numeric control is labeled `x in` and the indicator `y out`:\n\n```python\n\u003e\u003e\u003e import autolv\n\u003e\u003e\u003e lv = autolv.App()\n\u003e\u003e\u003e vi = lv.open('test.vi')\n\u003e\u003e\u003e vi(**{\"x in\": 3, \"y out\": 0})\n\u003e\u003e\u003e vi[\"y out\"]\n4.0\n```\n\nWaveform Graph\n--------------\nThe Waveform Graph control can be a 1d array of y-axis values, 2d array of x-axis and\ny-axis values, or a cluster (t0, dt, Y) where t0 and dt are scalers and Y is the\ny-axis values.\n\n## As 1d array\n\n![graph_1d.vi](./doc/_static/graph_1d.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open(\"graph_1d.vi\")\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi.graph.value\narray([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])\n```\n\n## As 2d array\n\n![graph_2d.vi](./doc/_static/graph_2d.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open(\"graph_1d.vi\")\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi.graph.value\narray([[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],\n       [0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]])\n```\n\n## As cluster\n\n![graph_cluster.vi](./doc/_static/graph_cluster.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open(\"graph_cluster.vi\")\n\u003e\u003e\u003e vi.run()\n\u003e\u003e\u003e vi.graph.value\n[0.0, 1.0, (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)]\n\u003e\u003e\u003e vi.graph.t0\n0.0\n\u003e\u003e\u003e vi.graph.dt\n1.0\n\u003e\u003e\u003e vi.graph.Y\narray([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])\n```\n\n## Tab control\n\n![tab control.vi](./doc/_static/tabctrl.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open(\"tab control.vi\")\n\u003e\u003e\u003e vi.tabcontrol.page1.cluster.b\n0.0\n```\n\n## Project\n\n```python\n\u003e\u003e\u003e project = lv.open('\u003cfile\u003e.lvproj')\n\u003e\u003e\u003e vi = project.open('\u003cfile\u003e.vi')\n```\n\n## Reordering cluster controls\nClusters in the Silver visual style need to be reordered after opening the VI.\n\n![silver error cluster.vi](./doc/_static/silver_errclstr.png)\n\n```python\n\u003e\u003e\u003e vi = lv.open(\"silver error cluster.vi\")\n\u003e\u003e\u003e vi[\"error in\"]\nCluster({'code': True, 'source': , 'status': False})\n\u003e\u003e\u003e cluster = vi[\"error in\"]\n\u003e\u003e\u003e cluster.reorder_controls([\"status\", \"code\", \"source\"])\n\u003e\u003e\u003e vi.read_controls()\n\u003e\u003e\u003e vi[\"error in\"]\nCluster({'status': True, 'code': 1, 'source': abc})\n```\n\n## VI's Context Help\n```python\n\u003e\u003e\u003e print(vi.context_help())\n\u003e\u003e\u003e vi.set_context_help(\"Does stuff...\")\n\u003e\u003e\u003e help(vi)\n```\n\n\nNotes\n-----\n- LV Controls have a Label attribute. ActiveX calls this Label 'name' and this is\nthe only mechanism for set/get a Control. So, the Label must be unique among\nthe front panel controls.\n- As a best practice, it is recommended to set the Label to a valid Python identifier.\nThis increases productivity when using dot-access in an interactive session such as\nIPython.\n- If your machine has multiple LabVIEW versions, launch the desired version first\nbefore interacting with it in Python.\n- LV's 'Time Stamp' comes across ActiveX as naive and represented in Python\nas datetime.datetime.\n- LabVIEW's FXP and Waveform data types are not supported\n- Array's of clusters can be read but not set\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fl-johnston%2Fautolv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fl-johnston%2Fautolv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fl-johnston%2Fautolv/lists"}