Skip to content

Add plugin lock monitor #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Conversation

zakv
Copy link
Contributor

@zakv zakv commented Feb 6, 2021

This PR would add a plugin called "lock monitor" to blacs. Since plugins are able to be distributed separately from blacs, adding this to the official blacs repo definitely isn't necessary. However since laser locks are ubiquitous among labscript users I thought I'd see what you all thought about including it with blacs? Including it might be particularly helpful for folks who don't have a developer install of blacs, as I'm not sure if they can easily add plugins.

image

A lot of details about the plugin are provided in the readme. Briefly the plugin is designed to call user-written code to check if lasers are in lock and optionally call user-written code to lock a laser when it is found to be out of lock. The user-written code is called during some of the plugin callbacks in blacs.experiment_queue.QueueManager.manage(). The plugin itself sandboxes user code in worker processes and handles aborting and re-queueing shots when lasers go out of lock. It also pauses the shot queue when a laser cannot be locked. Controls for lockers are provided in a blacs plugin tab which also includes an output box for displaying log messages from the lockers. A settings tab is provided for adding/removing lockers.

A readme is provided, as well as base classes for the locker classes that the user must write. Dummy locker classes are also provided. They don't control any real hardware but they do demonstrate how to write locker classes and can be used with lock monitor like real lockers.

Note that running this plugin requires #87 due to #86. Also, thanks to @philipstarkey for pointing me to some good references for writing blacs plugins!

@zakv
Copy link
Contributor Author

zakv commented Feb 6, 2021

A few questions and points maybe worth mentioning...

  • The readme can be seen in its rendered form here https://github.com/zakv/blacs/tree/lock-monitor/blacs/plugins/lock_monitor
  • There are a lot of f-strings; is that kosher? Blacs' setup.cfg mentions Python 3.6+ so I think they're ok, but I could change them to use .format() instead if necessary.
  • I think I set the copyright correctly in the .py files. Does the readme need them as well?
  • The LockFailureNotification class has inmain_decorator() on some of its methods because I thought it would be necessary when editing GUI widgets. Other plugins don't seem to have that though, so maybe it's not necessary?
  • The PluginTab class doesn't have the support for using the blacs state machine that the Tab class does, which is why lock monitor uses callbacks rather than transition_to_manual() etc.
    • This has the consequence that the "Force Lock" and "Restart Worker" buttons don't actually lock the laser or restart the worker when blacs is idle. The actions won't be taken until a shot is run, at which point blacs calls the pre_transition_to_buffered callback.
    • I briefly tried using a normal Tab instead of a PluginTab to work with the blacs state machine. However using Tab required adding a bunch of workarounds that were getting pretty hacky pretty quickly so I abandoned that idea.
  • In the examples on how to set up a logger I demonstrate how to use the logging module directly instead of using labscript_utils.setup_logging.setup_logging()
    • This was done primarily because setup_logging() doesn't work with jupyter notebooks (see error below), and using jupyter notebooks makes developing locker classes much easier.
    • Using logging directly also makes it possible to create separate log files for each locker and organize them into one folder in the labscript log directory.

For reference, the error raised when using setup_logging() in a jupyter notebook (or importing a module that uses setup_logging() into a jupyter notebook) is included below. It has something to do with the way jupyter handles stdout and stderr.

Jupyter Error
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-30-b2967eed1dc1> in <module>
      1 from labscript_utils.setup_logging import setup_logging
      2 
----> 3 setup_logging('jupyter_test')

c:\users\username\software\labscript\labscript-utils\labscript_utils\setup_logging.py in setup_logging(program_name, log_level, terminal_level, maxBytes, backupCount)
     53     handler.setLevel(log_level)
     54     logger.addHandler(handler)
---> 55     if sys.stdout is not None and sys.stdout.fileno() >= 0:
     56         stdout_handler = logging.StreamHandler(sys.stdout)
     57         stdout_handler.setFormatter(formatter)

UnsupportedOperation: fileno

@matth2peters
Copy link

matth2peters commented Dec 31, 2022

I'm having an issue with this code. It seems to work for the DummyLocker except for when I shut down blacs. I then get the error:
Traceback (most recent call last): File "c:\users\matth\labscript-suite\python_38\lib\site-packages\qtutils\invoke_in_main.py", line 46, in event result = event.fn(*event.args, **event.kwargs) File "c:\users\matth\labscript-suite\python_38\custom_python_packages\zak_blacs\blacs\blacs\__main__.py", line 605, in on_save_exit tab.shutdown_workers() File "c:\users\matth\labscript-suite\python_38\custom_python_packages\zak_blacs\blacs\blacs\tab_base_classes.py", line 212, in f self.event_queue.put(allowed_modes,queue_state_indefinitely,delete_stale_states,[function,[args,kwargs]]) AttributeError: 'LockMonitorTab' object has no attribute 'event_queue'

It seems like in the tab_base_classes.py file the PluginTab class (which LockMonitorTab inherits from) has no shutdown_workers method. Should PluginTab inherit from the Tab class, or is there something else that I'm missing?

@zakv
Copy link
Contributor Author

zakv commented Dec 31, 2022

It seems like in the tab_base_classes.py file the PluginTab class (which LockMonitorTab inherits from) has no shutdown_workers method. Should PluginTab inherit from the Tab class, or is there something else that I'm missing?

I did run into an issue like that (#86) when developing this plugin, and made a separate PR (#87) to fix it. I don't think that the branch for this PR includes the fix from that other PR though, which may be why you're seeing this issue. Could you try rebasing this branch on master in your local copy of the blacs repo? If that does work, then I can update this PR.

That said, the traceback you provided looks slightly different than I would expect if the issue were just that the LockMontiorTab class is missing a shutdown_workers() method though (seems like it's missing an event_queue attribute). So I'm not 100% sure this will fix it, but fingers crossed

@matth2peters
Copy link

That fixed it, thanks!

zakv added 5 commits January 2, 2023 14:54
…ed before.

Previously its Setting class could handle when self.data['import_paths'] wasn't set, but the Plugin class would get tripped up. To work around this, the default value for that key is set in Setting.__init__() now.
The issue was that the same name was given for the logger for both the DummyLocker and DummyScanZoomLocker, which meant that they actually shared one logger. This led to dupplicated outputs, probably due to multiple handlers being added to the same logger.
The new screenshot no longer shows the duplicated logging entries issue resolved by the previous commit.
@zakv
Copy link
Contributor Author

zakv commented Jan 2, 2023

That fixed it, thanks!

Perfect! Thanks for checking, I just updated this PR by rebasing its branch on master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants