6.4.4. Plugin cookbook
Most of the work of a plugin is the communication with the instrument, and it depends on how the instrument is reached: a text protocol, a serial line, VISA, a DLL, a .NET assembly… The package pymodaq_plugins_mockexamples holds a cookbook: short, tested plugins, one for each of these ways, to copy from when writing the plugin of your instrument.
Each recipe runs without hardware: it talks to a simulated device (a mock) written for it, so you can try it in the
Dashboard, read it, and run its tests. Where a recipe has a port or an address, leave it to MOCK to use the simulated
device; give the real one to talk to your instrument.
How to use a recipe:
Choose the recipe in the list below and read the header of its files: it tells what to copy, what to adapt (the commands and the parameters of your instrument) and what to keep (the parts that PyMoDAQ needs and that are easy to get wrong: threads, master and slave, units…).
Put the communication with the instrument in a class of the hardware folder of your package, as the recipes do, and keep the plugin files thin (see Instrument Plugins).
Test your plugin as the recipes do, against a simulated device and the tools of
pymodaq.utils.plugin_testing(see Testing the behaviour of your plugin without hardware). A test on a simulated device checks your side of the contract with PyMoDAQ, not the device: say what was tried on the real instrument.
The files of the recipes are in src/pymodaq_plugins_mockexamples/ of the repository. The README of the package has a
table of them (cookbook of device patterns).
6.4.4.1. The recipes
- An instrument with a text protocol (commands such as
*IDN?): pymeasure (recommended) daq_move_CookbookPymeasure,daq_0Dviewer_CookbookPymeasureandhardware/pymeasure_source.py. The instrument is described in a few declarative lines with pymeasure (the commands to read and set a value, the validators, the checking of errors). Its tests send the exact commands of the manual to a protocol adapter, and also run on a simulated device.- A serial line (RS-232, USB-serial)
daq_move_CookbookSerial,daq_0Dviewer_CookbookSerialandhardware/serial_stage.py. A driver written directly onpyserial: the terminations of the commands, the timeouts treated as errors, one lock because the driver is shared by the actuator and the detector, the error queue of the device and a homing that blocks until it is over and then callsmove_done.- VISA / SCPI instruments
daq_move_CookbookVisa,daq_0Dviewer_CookbookVisaandhardware/visa_meter.py. The same on apyvisaresource: explicit terminations and timeout,queryversuswrite.- A DLL from the manufacturer (C library)
daq_move_CookbookDll(three axes),daq_0Dviewer_CookbookDllandhardware/dll_controller.py. Actypesdriver: theargtypesandrestypeof each function, the opaque handle,byref, a structure filled by the library, error codes turned into exceptions and a callback that the library calls from one of its threads (it is kept alive, and it only emits a Qt signal). The library is replaced by an object used like the loadedCDLL, so the code of the driver is the real one.hardware/native_library.pyloads a library (names per platform, path from a setting or an environment variable, an error that lists what was tried) andhardware/system_library_demo.pyshows the techniques on the C library of the system.- A .NET assembly from the manufacturer
daq_move_CookbookDotNet(three axes),daq_0Dviewer_CookbookDotNet,hardware/dotnet_controller.pyandhardware/dotnet_runtime.py. A pythonnet driver: theoutparameters that come back in a tuple, the events given a Python function, the exception type of the assembly,IDisposable. The assembly is replaced by an object used like its namespace.hardware/system_dotnet_demo.pyshows the techniques on the .NET libraries of the runtime.pythonnetneeds a .NET runtime only when it talks to an assembly.- A Python package from the manufacturer
There is no recipe: put it behind a class of the hardware folder, created by
ini_stageorini_detector, as the drivers above, so that a simulated version of this class can replace it in the tests.- A camera
daq_2Dviewer_CookbookCameraandhardware/mock_camera.py: the recipe to copy for a real camera. The plugin is aCameraBaseofpymodaq_plugins_utils(acquisition in a thread of its own, live and snap, averaging, the ROI drawn in the viewer, binning, FPS) and the driver follows theCameraDriverBaseinterface of the same package, with the method names of pylablib.daq_2Dviewer_BSCameraandhardware/beam_steering.pyare the camera of the beam steering demonstrations, a plain plugin on purpose: what a camera driver gives its plugin, a region of interest and a binning applied by the camera (the image is smaller), an exposure time, and axes calibrated in µm that follow them.daq_2Dviewer_RoiStuffis the other way to select a region: it is drawn in the viewer, received by the plugin inroi_selectand applied to the data after the grab.- A spectrometer
daq_1Dviewer_CookbookSpectrometer,daq_move_CookbookSpectrometerandhardware/spectrometer.py. A detector whose axis (the wavelength in nm) changes because another module, here the actuator that turns the grating, moves it: the axis is asked to the instrument at every grab and sent with the data. The actuator is a slave of the detector and shares its instrument. The detector has the methods (get_spectro_wl,set_laser_wl…) that the spectrometer extension calls.