This is a follow up to the I2K2020 course.
For alignment in a lightsheet microscope, I want to display live xz (or yz) sections.
I use uManager
to control the camera, and thought about using pycro-manager
to grab the images and relay them to napari
for display. Data could be sliced using the inbuild napari
“roll dimensions”, or using numpy
to swap the axes.
No need to save the data, this is really just for alignment purposes.
Here is the documentation of my failures
(code is run from a jupyter-lab
notebook)
First attempt: run multi_d_acquisition
in a loop and send each stack to napari
.
from pycromanager import Dataset, Acquisition, multi_d_acquisition_events
import napari
import numpy as np
v = napari.Viewer()
v.add_image(np.zeros([512,512]), name = 'uManager', contrast_limits=[0,5000])
for ii in range(2):
with Acquisition(directory=save_dir, name=save_name, show_display=False) as acq:
events = multi_d_acquisition_events(num_time_points = 10)
# timepoints are z-slices since z-stage control is currently from outside of uManager
acq.acquire(events)
# read the data that was just acquired
dataset = Dataset(acq.get_disk_location())
dask_array = dataset.as_array()
v.layers[0].data = dask_array
Works in principle, but has some issues:
- saves the data to hard drive, then reads from hard drive to display in napari - so will fill up storage quickly, plenty of overhead
- updates napari display only at the end of the loop, so useless for my goal
@henrypinkard suggested to use an image_process_fn
:
- should relay data to napari
- suppress saving to disk
from pycromanager import Dataset, Acquisition, multi_d_acquisition_events
import napari
import numpy as np
def stream_napari(image, metadata):
global v
v.layers[0].data = image
v = napari.Viewer()
v.add_image(np.zeros([512,512]), name = 'uManager', contrast_limits=[0,5000])
for ii in range(2):
with Acquisition(directory=None, name=None, show_display=False, image_process_fn = stream_napari) as acq:
events = multi_d_acquisition_events(num_time_points = 10)
# timepoints are z-slices since z-stage control is currently from outside of uManager
acq.acquire(events)
Still doesn’t work:
- napari display is only updated at the end of the for-loop
- with the
image_process_fn
, I’m only sending the active z-slice to napari, so I cannot display z-sections
I then tried to use a dummy image_process_fn
, only to avoid saving the data and the Acquisition.get_dataset()
function to pass the data to napari.
from pycromanager import Dataset, Acquisition, multi_d_acquisition_events
import napari
import numpy as np
def stream_napari(image, metadata):
return image, metadata
v = napari.Viewer()
dataset = np.zeros([10, 512,512])
v.add_image(dataset, name = 'uManager', contrast_limits=[0,5000])
for ii in range(2):
with Acquisition(directory=save_dir, name=save_name, show_display=False, image_process_fn = stream_napari) as acq:
events = multi_d_acquisition_events(num_time_points = 10)
# timepoints are z-slices since z-stage control is currently from outside of uManager
acq.acquire(events)
dataset = acq.get_dataset()
dask_array = dataset.as_array()
v.layers[0].data = dataset
Seems I found a not-yet implemented function?
I’m struggling to understand how/if I can pass more arguments into the image_process_fn
, and where I would grab the returns. Could I use an image_process_fn
to assemble the stack, and only relay to napari once the stack is complete?
I’m now out of ideas and any help would be greatly appreciated!