Help for plugin design - synchronized display of multiple images and graphs


#1

Hi everybody,

We have a setup in our lab where we acquire unsynchronized data from multiple devices. There are two camera which have a different frame rate, two micromanipulators, a linear actuator, a pressure control system, all having different acquisition rates. The starting time of the acquisition may vary between devices.

Typically, I get a folder like this (https://github.com/NicoKiaru/Controller42/tree/master/ExampleData/Exp_0) containing informations about each device.

Ideally, I’d like to make a plugin which can:

  • fetch the devices informations (type of device, acquisition parameters (starting date, acquisition rate),
  • display a window for each device (an image if it is a camera, a “live graph” if it is an actuator, some other custom display for custom devices)
  • keeps every window synchronized : if I move the slider of any of these windows, thanks to these parameters, the plugin updates all windows.

So here are my questions :

  • first of all, if you think that’s a bad idea because there are some more fitted software to do that, let me know! It’s always good to be aware of alternatives.

  • second, do you have general advices on how to achieve this ? Should I write several commands ? What sort of commands (initialize / synchronize / stop synchronize) ? IJ1 / IJ2 ? Maybe there are some good examples from which I can get some inspiration.

Thank you all!


#2

Maybe MicroManager could be a sustainable solution:

https://micro-manager.org/

You can control multiple devices scripted, etc.:

https://micro-manager.org/wiki/Micro-Manager_Programming%20Guide#Working_with_multiple_devices

An extensive API is available, too:

https://micro-manager.org/wiki/Micro-Manager_Programming_Guide#APIs


#3

Thanks for your suggestion @Bio7 , indeed micromanager is a very good software for the acquisition. However I currently use matlab for the acquisition and it is working fine (in fact I use inside matlab a part of micromanager for controlling the microscope).

Sorry it was not super clear, but my problem is not about the acquisition but rather about making a convenient display of these acquisitions. I checked quickly in Micromanager, and I couldn’t find anything related to displaying multiple unsynchronized devices, after the acquisition is made.


#4

I think for this kind of implementation an Observer pattern would be appropriate:

I implemented, e.g., something similar to synchronize different Eclipse views with the JavaFX SceneBuilder

Here a YouTube video:


#5

Thanks again a lot @Bio7, you directed me in the right direction and I managed to get what I wanted :

The wide field view has more than 2000 images while the fluorescent has 116. Also the acquisitions do not stop and start at the same date.

This is super useful for “unsynchronized” images or any other unsynchronized device which outputs a graph. There’s a few tricks I used in the implementation which are specific to my case but nonetheless I think there’s a skeleton that can be used for any image, provided the acquisition date and sampling rate are given.


#6

I have another question concerning the structure of what I’m doing here.

Currently I made an IJ command, in which I create a non-static object (called “timeSynchronizer”) that contains a list of all synchronized objects/displays.

Now let’s say that I want to create another command that’s modifying this list (removes or adds one display). How can I retrieve the previously created object (timeSynchronizer) ?

I see different options. Maybe someone can tell which way is better:

  1. Make the timeSynchronizer object static
  2. Use the ObjectService somehow, to store and retrieve timeSynchyronizers objects
  3. Create a new Service called timeSynchronizerService, which stores and dispatch timeSynchronizers objects
  4. Something else!

Thanks for your advice,

Nicolas


#7

I don’t know if that’s the best, but the ObjectService does exactly what I want.
I declare this service as a parameter:

    @Parameter
    private ObjectService objService;

With this service, I can store the timeSynchronizer object (that contains a unique id): objService.addObject(timeSynchronizer);

And when I want to retrieve timeSynchronizer in another command, I again declare an ObjectService as a parameter, then looks for the object with a correct id using:

TimeSynchronizer mySync;
for (TimeSynchronizer synchronizer : objService.getObjects(TimeSynchronizer.class)) {
    if (synchronizer.id.equals(correctId)) {
        mySync=synchronizer;
        break;
    }
}

Let me know if there’s a better option.