mabuchilab / Instrumental

Python-based instrumentation library from the Mabuchi Lab.
http://instrumental-lib.readthedocs.org/
GNU General Public License v3.0
120 stars 80 forks source link

Observer or Callback mechamism #85

Open Tillsten opened 5 years ago

Tillsten commented 5 years ago

Hi,

I am thinking about using Instrumental, but what I am missing is the ability to observe certain device values. This can simplify GUI writing a lot. Do I miss something or is this not supported?

greetings Till

jondoesntgit commented 5 years ago

It sounds like you’re wanting to poll devices periodically for some quantity, is this correct?

Sent with GitHawk

Tillsten commented 5 years ago

In some cases polling may be involved, but for most cases polling is not necessary.

I am more looking for something like some functinalty which in Qt-signals, traitlets, traits or atom. Let's say the device is camera with a settable gain and a Label showing the gain. Right now, if you change the gain at any point in the code, you have to update the label manually in the same step. If you have e.g. _gain_changed observer, you use a callback to update your label.

jondoesntgit commented 5 years ago

I don’t have enough experience writing GUIs for instrumentation. I think Hernan Grecco’s lantz (or lantz-project) may have some more of this baked into their repository.

doddgray commented 5 years ago

No, this isn't really baked into Instrumental right now. That said, I've had an easy time making lightweight persistent GUIs for plotting streamed data from instrumental-interfaced instruments using a combination of socket https://docs.python.org/3/library/socket.html and PyQtGraph http://www.pyqtgraph.org/ (on suggestions from @natezb, Instrumental's legendary creator) for TCP/IP service and plot GUI coding, respectively. Separating it into a data-streaming server and a plotting client has a couple really nice benefits

  1. You can live-stream data from an instrument to a persistent plot GUI and simultaneously and asynchronously perform data collection with another python kernel (eg. in a Jupyter notebook). This is not possible if you're only running one python kernel.
  2. The data stream server can easily be accessed by other computers on your local network, so you can hook up instruments to lab computers that are always on and running the little python-based server code, and then access the data stream for live plotting or data collection on other computers, or multiple computers at the same time (eg. one plotting the data near the experiment, one collecting/saving/analyzing data elsewhere).

Here are example python scripts that do this with an instrumental-connected Bristol 721 IR spectrometer. Sorry the code is messy and largely copied from other sources, but it does work well and could be adapted for some other instrument just by changing a few lines. https://github.com/doddgray/experiment_control/blob/master/bristol721_server.py https://github.com/doddgray/experiment_control/blob/master/PlotBristol.py

natezb commented 5 years ago

This was one of the use cases I had in mind when introducing Facets, which are similar to Lantz's Feats (which have this GUI stuff baked in). Since Facets are basically properties with some extra features, callbacks should be pretty quick and simple to add.

It would be nice to have optional GUI support that lets you create "test panels" as Lantz allows you to do, but should not require everyone who uses Instrumental to have Qt installed.

natezb commented 5 years ago

Check out the changes in 82a23b841f15491d3e9b3746d4baeb176b78d40a. This adds an observe() method to the Instrument base class, which lets you register a facet observer on a per-instance level.

For example, let's say I have an MXG function generator and I want to print changes to the frequency:

    >>> mxg.observe('cw_frequency', print)
    >>> mxg.cw_frequency += Q_(1, 'MHz')
    ChangeEvent(name='cw_frequency', old=<Quantity(933330000.0, 'hertz')>, new=<Quantity(934330000.0, 'hertz')>)

Note that this doesn't track changes made on an instrument's front panel, it only knows about changes made through the Facet interface.

Let me know what you think, the API is still very much open to change.