{ "info": { "author": "Alexander Bj\u00f6rling", "author_email": "alexander.bjorling@maxiv.lu.se", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# acquisition-framework\nLight weight data acquisition framework for orchestrating beamline experiments.\n\nThe code is organized as a library containing various classes. A beamline is set up simply by making instances for detectors, motors, and any other devices directly in ipython. See `dummy_beamline.py` for example.\n\n## macros\nA macro is a short expression in command line syntax which can be directly run at the ipython prompt. The following is a macro.\n```\nmv samx 12.4\n```\n\nIn this framework, macros are created by writing a class with certain properties and marking that class with a decorator. This registers the macro as a magic ipython command. All available macros are stored in a central list, and can be listed with the `lsmac` command. The macro syntax is similar to sardana and spec.\n```\nIn [2]: lsmac\n\nname class \n---------------------------------------------------------------\nascan \nct \ndmesh \ndscan \nliveplot \nloopscan \nlsdet \nlsm \nlsmac \nlsrec \nmesh \nmv \nmvd \nmvr \nnpointflyscan \nsetlim \nsetpos \nspiralscan \nstartlive \nstoplive \ntweak \nuserlevel \nwa \nwm \n\nDo ? (without <>) for more information.\n```\n\nNote how macros aren't stored in a special library. They are written throughout the library wherever they make sense. For example, in `Detector.py` where the detector base classes are defined, the `lsdet` macro is defined as follows.\n```\n@macro\nclass LsDet(object):\n def run(self):\n dct = {d.name: d.__class__ for d in Detector.getinstances()}\n print(utils.dict_to_table(dct, titles=('name', 'class')))\n```\n\nNote that a macro is different from a script. Anyone can easily write a macro, but for composite operations where existing macros are just combined it is faster to write a script. The following is a script, not a macro, but uses a special `runCommand` function to interface with the command line syntax.\n```\nfrom lib.environment import runCommand\n\nfor i in range(5):\n runCommand('mv samy %d' % new_y_pos)\n runCommand('ascan samx 0 1 5 .1')\n\n```\n\n## environment variables\nNo global environment variables are used. Instead, a central object in the environment module is used to store values such as scan number etc.\n```\nIn [24]: from lib.environment import env\n\nIn [25]: env.nextScanID\nOut[25]: 1\n```\n\n## detector selection\nDetectors have an `active` attribute which determines if they are included in data acquisition such as scans. The macro `lsdet` indicates if each detector is active with an asterisk.\n```\nIn [2]: lsdet\n\n name class \n--------------------------------------------------------\n* det2 \n* det3 \n* det1 \n\nIn [3]: ct\ndet2 : 0.5862324427414796\ndet3 : (100,)\ndet1 : 0.815299279368746\n\nIn [4]: det3.active=False\n\nIn [5]: lsdet\n\n name class \n--------------------------------------------------------\n* det2 \n det3 \n* det1 \n\nIn [6]: ct\ndet2 : 0.26999817158517125\ndet1 : 0.4045182722290984\n```\n\n## instance tracking\nThe framework has no databases or central registries. Instead, objects are related through inheritance. A common base class `Gadget`\nis inherited by detectors, motors, as all the rest. `Gadget` and all of its subclasses keep track of their instances. An example follows.\n```\nIn [1]: [m.name for m in Motor.getinstances()]\nOut[1]: ['gap', 'samy', 'samx']\n\nIn [2]: [d.name for d in Detector.getinstances()]\nOut[2]: ['det1', 'det3', 'det2']\n\nIn [3]: [g.name for g in Gadget.getinstances()]\nOut[3]: ['gap', 'detgrp', 'det1', 'samy', 'samx', 'det3', 'det2', 'hdf5recorder']\n```\n\n## recorders\nData is captured by recorders. Recorders are run in separate processes and get data through queues, avoiding holding up the main acquisition loop because of I/O. They can do anything with the data, for example saving to `hdf5` files or live plotting. See the `Hdf5Recorder` and `PlotRecorder` classes for examples. The former is very primitive still, but the latter is quite nice.\n\nNote how easy it is to write these recorders, and how easy it would be to integrate online data analysis, for example writing a recorder which serves data (or links to data) for an on-the-fly ptycho engine to grab.\n\nThe `lsrec` macro lists currently running recorders.\n```\nIn [30]: lsrec\n\nname class \n----------------------------------------------------------------\nhdf5recorder \nname \n```\n\n## user levels\nAll `Gadget` instances have an associated user level. This means that certain motors can be hidden and protected while others are exposed through the macros. In this example, two sample motors are available to everyone while the undulator gap is higher level. This is not a security feature but meant to simplify the environment and reduce the risk of mistakes\n```\nIn [7]: env.userLevel\nOut[7]: 1\n\nIn [8]: wa\nsamy 0.0\nsamx 0.0\n\nIn [9]: env.userLevel = 5\n\nIn [10]: wa\nsamy 0.0\ngap 0.0\nsamx 0.0\n```\n\n## direct access to python objects\nIf `Gadget` objects operate on underlying Tango devices, then Tango attributes are directly accessible on the objects themselvs. PyTango provides tab completion and so these can be easily checked or corrected. Of course `Gadget`subclasses can provide nice getter and setter methods, but fixes are easily done.\n```\nIn [7]: pilatus.det.energy\nOut[7]: 10.0\n\nIn[8]: pilatus.lima.saving_mode\nOut[8]: 'MANUAL'\n```\n\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/alexbjorling/contrast", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "contrast", "package_url": "https://pypi.org/project/contrast/", "platform": "", "project_url": "https://pypi.org/project/contrast/", "project_urls": { "Homepage": "https://github.com/alexbjorling/contrast" }, "release_url": "https://pypi.org/project/contrast/0.0.1/", "requires_dist": null, "requires_python": ">=3.6", "summary": "Light weight data acquisition framework for orchestrating beamline experiments.", "version": "0.0.1" }, "last_serial": 5892822, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "8f5a9640d48cb63bb17d529ae76aebdf", "sha256": "e6233e8933c5ecb18231614185d0f7364d9f9c4357168285c79cd8ac08950490" }, "downloads": -1, "filename": "contrast-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "8f5a9640d48cb63bb17d529ae76aebdf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 39551, "upload_time": "2019-09-26T21:23:16", "url": "https://files.pythonhosted.org/packages/e2/41/9766bce9289c8f2385269ea23de6be625d9acea891f98e635d125d6be58b/contrast-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "11562967915057e1b29fde37aed917e5", "sha256": "8b431565490a183c1b2f77725aff8b5d1581f85323f817ea1a092deec11a5cd8" }, "downloads": -1, "filename": "contrast-0.0.1.tar.gz", "has_sig": false, "md5_digest": "11562967915057e1b29fde37aed917e5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 28068, "upload_time": "2019-09-26T21:23:19", "url": "https://files.pythonhosted.org/packages/02/56/6a730ed85db0646d69bf710640f3febf5b8bbb518ff82e688c1b9b74b2c5/contrast-0.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8f5a9640d48cb63bb17d529ae76aebdf", "sha256": "e6233e8933c5ecb18231614185d0f7364d9f9c4357168285c79cd8ac08950490" }, "downloads": -1, "filename": "contrast-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "8f5a9640d48cb63bb17d529ae76aebdf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 39551, "upload_time": "2019-09-26T21:23:16", "url": "https://files.pythonhosted.org/packages/e2/41/9766bce9289c8f2385269ea23de6be625d9acea891f98e635d125d6be58b/contrast-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "11562967915057e1b29fde37aed917e5", "sha256": "8b431565490a183c1b2f77725aff8b5d1581f85323f817ea1a092deec11a5cd8" }, "downloads": -1, "filename": "contrast-0.0.1.tar.gz", "has_sig": false, "md5_digest": "11562967915057e1b29fde37aed917e5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 28068, "upload_time": "2019-09-26T21:23:19", "url": "https://files.pythonhosted.org/packages/02/56/6a730ed85db0646d69bf710640f3febf5b8bbb518ff82e688c1b9b74b2c5/contrast-0.0.1.tar.gz" } ] }