Micro-Manager - How to do line-scanning using "Multi-Dimensional Acquisition"


I’m new to Micro-Manager and would like to give it a shot for controlling a custom-made stage-scanning confocal setup. The stage system is a Mad City Labs Nano-PDQ350/375 + Nano-Drive 85 Controller connected to my laptop.

In Micro-Manager, I found the “Multi-Dimensional Acquisiton” menu which seems to be useful for defining sequences of stage positions, but it appears that all positions need to be “clicked together” manually. Is there maybe a way to read in e.g. a text file with X and Y positions, which I could conveniently generate using a script?
For example, if I wanted to scan a 10 um x 10 um area with a step size of 10 nm, I would have to type in 1000 x 1000 = 1.000.000 points by hand (which is obviously not very practical).
Alternatively, is there a way to write the whole measurement procedure into a script which is then read in and executed by Micro-Manager?

Finally, is it possible to send a trigger signal to the camera after each step, incl. a user-defineable wait period (e.g. wait period = camera integration time + stage settle time)?

Many thanks for your help!

Kind regards,

I think you can accomplish all this using various features in pycro-manager. Happy to answer more specific questions after you’ve had a chance to give the documentation a read through


Hi @henrypinkard,

thanks for your help! I’m doing most of my scripting work in Python, so this looks very promising. I’m using Jupyter Notebook on Windows 10 by the way. I’m currently looking into Pycro-Manager and just stumbled into the first issue:

After installing the Pycro-Manager package and doing

from pycromanager import Bridge

bridge = Bridge()

nothing happens. The cell remains busy/keeps executing indefinitely… What might be the problem here?

In the documentation, it’s suggested to install Micro-Manager 2.0. However, I absolutely need to use the latest Micro-Manager 1.4 nightly build, because that’s the only version where Andor has implemented all their camera drivers. Does Pycro-Manager also work with version 1.4 nightly? Also, does Micro-Manager have to be running first?

Thanks and best regards,

Hi @Joanna,

That is the first time I heard of this. We have so far kept the device adapters the same between the two versions. Which Andor drivers are missing from 2.0 gamma? Please note that 1.4 is no longer updated, and you would need to backport changes (like the addition of Pycro-Manager) yourself.



Hi @nicost,

I need to connect an iXon Ultra EMCCD camera and actually started off with version 2.0, but discovered that in the Hardware Configuration Wizard the “Andor” folder with the “Andor | Generic Andor Camera Adapter” was missing (there was only a “AndorSDK3 (unavailable)” at the bottom). When I wrote Andor support, they suggested

“The iXon driver (and drivers for all Andor CCD cameras – not sCMOS) is now included with the installation of uManager so there shouldn’t be any need to install the driver pack if the customer is using a recent version of uManager – I would always advise installing the latest nightly build of v1.4:- https://valelab4.ucsf.edu/~MM/nightlyBuilds/1.4/Windows/

I installed the latest version 2.0 in 64-bit from https://valelab4.ucsf.edu/~MM/nightlyBuilds/2.0.0-gamma/Windows/MMSetup_64bit_2.0.0-gamma1_20210418.exe.


The Andor folder should be present, but there have been some recent changes to the build system that may have resulted in problems. I need access to hardware and will be able to sort this out tomorrow. However, if you have a chance, can you start 2.0, select Help > report a problem, start the Hardware Configuration Wizard, convince yourself the Andor folder is not present, and then send the report?

1 Like

Hi @nicost,

I just reinstalled version 2.0 and - voilà - the camera is immediately supported, i.e. I can now load my configuration file created with version 1.4 and everything seems to work. :smile: This wasn’t the case when I first installed version 2.0 and I suspect the reason is that, this time, I already had the “Andor Driver Pack” installed:


…unfortunately, Pycro-Manager still won’t connect even with 2.0 succesfully running. I also tried adding the Micro-Manager directories (both 1.4 and 2.0) to PYTHONPATH, but that didn’t seem to be the problem. @henrypinkard, anything else I could try or check?


Make sure you’re using latest versions of both PM and MM, and that youve selected tools-options, and checked the box that says Run server on port 4827


Hi @henrypinkard,

both PM and MM are now the latest available versions (0.12.8 and 2.0) and I also enabled Run server on port 4827 (it was disabled before), but to no avail… I tried both in Jupyter and directly from the console/Python interpreter.

Okay, now it works!! I’m finally getting the

<pycromanager.core.mmcorej_CMMCore object at 0x000002EC89ED5550>

:star_struck: :star_struck: :star_struck:

And it clearly says in the documentation to enable the server on port 4827, must have missed that bit…

Quick question: If Micro-Manager is running with user-defined presets in the hardware configuration and if I then trigger an acquisition using Pycro-Manager, will the acquisition automatically run according to those presets? Or will the camera fall back to its own “factory default settings”?

Micro-Manager sees the equipment as “State Machines”. Once it sets the state, that state should not change, unless something else changes it. So, as long as you (or PycroManager) does not change the state, it will stay the same.

@nicost Okay, merci! I’ve tried some very basic things, such as

import pycromanager as pm

bridge = pm.Bridge()
core = bridge.get_core()
exposure = core.get_exposure()


But while PM seems to be able to talk to MMCore, with other calls such as get_exposure() the Jupyter cell just loads indefinitely. In this case for example, shouldn’t it print the exposure time?

It’s the first example on Controlling Micro-Manager core — pycro-manager documentation

The other ones, such as acquiring images, don’t work either… :confused:

…neither does the minimal example for acquiring a z-stack on Specifying data to acquire — pycro-manager documentation

UPDATE: Okay, I tried the acquisition directly from the Python console and got the error

SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in position 2-3: truncated \UXXXXXXXX escape

It seems one needs to use r'C:\path-to-saving-dir' instead of just 'C:\path-to-saving-dir' in order to use raw string (or escape the backslashes).

…and now calling core.get_exposure() suddenly and magically works, after trying it once from the console. I’m moderately confused :face_with_raised_eyebrow:

…and now, it doesn’t work again. This is extremely frustrating.

Have you also encountered such “non-deterministic” behavior?


It seems that the acquisition only starts once I interrupt the Jupyter kernel. Is this maybe a bug?

From the Python interpreter, this happens:

from pycromanager import Acquisition, multi_d_acquisition_events

with Acquisition(directory=r'C:\Users\joanna\Desktop', name='z-stack') as acq:
...     # Generate the events for a single z-stack
...     events = multi_d_acquisition_events(z_start=0, z_end=10, z_step=0.5)
...     acq.acquire(events)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python39\lib\site-packages\pycromanager\acquire.py", line 404, in __init__
    core = self.bridge.get_core()
  File "C:\Program Files\Python39\lib\site-packages\pycromanager\core.py", line 348, in get_core
    self.core = self.construct_java_object("mmcorej.CMMCore")
  File "C:\Program Files\Python39\lib\site-packages\pycromanager\core.py", line 284, in 
  File "C:\Program Files\Python39\lib\site-packages\pycromanager\core.py", line 115, in send
  File "C:\Users\joanna\AppData\Roaming\Python\Python39\site-packages\zmq\sugar\socket.py", 
    line 555, in send_multipart
    return self.send(msg_parts[-1], flags, copy=copy, track=track)
  File "C:\Users\joanna\AppData\Roaming\Python\Python39\site-packages\zmq\sugar\socket.py", 
    line 505, in send
    return super(Socket, self).send(data, flags=flags, copy=copy, track=track)
  File "zmq\backend\cython\socket.pyx", line 718, in zmq.backend.cython.socket.Socket.send
  File "zmq\backend\cython\socket.pyx", line 765, in zmq.backend.cython.socket.Socket.send
  File "zmq\backend\cython\socket.pyx", line 247, in zmq.backend.cython.socket._send_copy
  File "zmq\backend\cython\socket.pyx", line 242, in zmq.backend.cython.socket._send_copy
  File "zmq\backend\cython\checkrc.pxd", line 28, in zmq.backend.cython.checkrc._check_rc
    zmq.error.ZMQError: Operation cannot be accomplished in current state

…what an absolute mess! It seems that (at least with Jupyter), for some reason, one has to explicitly exit from the with statement using VAR.__exit__():

from pycromanager import Acquisition, multi_d_acquisition_events

with Acquisition(directory='/path/to/saving/dir', name='acquisition_name') as acq:
    # Generate the events for a single z-stack
    events = multi_d_acquisition_events(z_start=0, z_end=10, z_step=0.5)

Otherwise, it just gets stuck.

Source: https://stackoverflow.com/a/49265028

Possible explanation: python - What does `exit` keyword do in Python3 with Jupyter Notebook? - Stack Overflow

I feel like this should be mentioned in the documentation (or am I the only person trying to use PM with Jupyter?)…


…aaand this didn’t solve it either. Even with VAR.__exit__() included, one actually has to terminate the Jupyter kernel for the acquisition to start.

Unfortunately, I don’t think Pycro-Manager is production-ready at this point, at least not using Jupyter.

Hi Joanna,

Many of us (including my group) are using Pycro-manager for complex hardware triggered acquisitions in both Python and Jupyter notebooks. You can see our github repo for an example of use in Python.

Do these errors occur with the demo configuration?

We have found it helpful to track potential issues down using the demo config and then move over to real hardware. This is true for both Micro-manager and Pycro-manager.

I just double checked that indeed these examples do work for me with a jupyter notebook and with the latest pycromanager/micromanager versions. I’m not sure what’s going on in your case, though it’s certainly possible its some kind of bug specific to your jupyter version/language settings/os/etc. As @dpshepherd notes, there are many people using PM in jupyter notebooks without issue. Happy to help you figure it out, but you’ll need to create a minimal, reproducible example so that I can debug on my end. Also, the best place to discuss this is on Github, where there are templates describing the most efficient ways to report bugs

@Joanna , just to clarify, the VAR.__exit__() in your example will cause an error because in your case you don’t have a variable name VAR. Regardless, calling __exit__() isn’t needed because __exit__ is called behind the scenes at the end of the with statement.

It looks like Acquisition.__exit__() will block until the acquisition is finished, so if your acquisition is freezing up for some reason it makes sense that the python script will also freeze at this point.

I suspect that the real cause of this is that something is freezing up at the hardware level rather than at the Python level.

@henrypinkard do you know if the acquisition engine saves enough logging information to pinpoint where this lockup is occurring?

1 Like

Good idea. If you run Acquisition(debug=False, core_log_debug=False), there will be logging information printed to both the python console and the core log in the corelogs folder in the micro-manager install directory. Though this wouldn’t explain the issues calling get_exposure. Switching to the demo configuration and seeing if this still happens with the demo camera would be a useful experiment

@henrypinkard I’m confused, should those keyword arguments to Acquisition be True rather than False?

1 Like

Oh yeah, you’re right