Skip to content
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

pycromanager acquisition with autofocus #352

Open
ieivanov opened this issue Feb 9, 2022 · 4 comments
Open

pycromanager acquisition with autofocus #352

ieivanov opened this issue Feb 9, 2022 · 4 comments
Labels
question Further information is requested

Comments

@ieivanov
Copy link
Collaborator

ieivanov commented Feb 9, 2022

Hi Henry,

I'm trying to compose an acquisition where I move between different XYZ positions, run an autofocus routine when I arrive at the new position, and acquire a Z stack relative to the new Z position after autofocus.

What is the best way to generate this sequence of acquisition events? I would like each XY position to be also associated with a Z coordinate to account for tilt in the sample and allow the autofocus device to stay within range. I am currently implementing the autofocus routine as a post_hardware_hook_fn with a call to core.full_focus() similar to your example notebook.

I am starting with code like this:

events = multi_d_acquisition_events(xyz_positions = [[100, 100, 50], [110, 110, 60]],
                                    z_start=-1, z_end=1, z_step=1)

def autofocus_fn(event, bridge, event_queue):
    if 'axes' in event.keys():
        if not hasattr(autofocus_fn, 'pos_index'):  # first position
            autofocus_fn.pos_index = event['axes']['position']
            mmc = bridge.get_core()
            mmc.full_focus()  # may change current z position
        if event['axes']['position'] != autofocus_fn.pos_index:  # different position
            mmc = bridge.get_core()
            mmc.full_focus()  # may change current z position
        autofocus_fn.pos_index = event['axes']['position']
    return event

with Acquisition(directory=r'D:', name='demo_pm_test', 
                 post_hardware_hook_fn=autofocus_fn) as acq:
    acq.acquire(events)

In this acquisition, autofocus_fn is called after the hardware is placed at position [100, 100, 49]. Ideally, I'd call autofocus at the center z position, here z=50, but that's easy to correct in the hook function. The call to mmc.full_focus() may change the current z position by del_z. Will the image at this event be acquired at z=49 or z=49+del_z? What about subsequent images? I'd expect the next image to be acquired at z=49+1+del_z, but I'm worried it may be acquired at z=50 as the event specifies. Will the metadata of the acquired images be updated if I change the hardware in an acquisition hook? Can you think of a better way to accomplish the acquisition I am describing?

In a related issue, I find that more documentation on the acquisition hook functions would be helpful. If I modify an event (e.g. change the hardware) in a post_hardware_hook_fn would those modifications take place? I can see this will happen in a pre_hardware_hook_fn, but I'm guessing the hardware won't change if I modify an event in a post_hardware_hook_fn. I've thought about creating a z stack by adding events to the event queue after the mmc.full_focus() call in the hook function. Do you think this will be a better approach?

@ieivanov ieivanov added the question Further information is requested label Feb 9, 2022
@henrypinkard
Copy link
Member

The call to mmc.full_focus() may change the current z position by del_z. Will the image at this event be acquired at z=49 or z=49+del_z? What about subsequent images? I'd expect the next image to be acquired at z=49+1+del_z, but I'm worried it may be acquired at z=50 as the event specifies.

It will be acquired at whatever is specified in the event after the pre_hardware_hook_fn, unless you manually change it in the post_hardware_hook. So you probably want to store del_z with hook function like autofocus_fn.offset = del_z and then reuse it on subsequent calls where you dont run the autofocus

If I modify an event (e.g. change the hardware) in a post_hardware_hook_fn would those modifications take place?

if you modify the event, nothing will change since the information in it was already used, but if you call the core and change the hardware, it will.

I've thought about creating a z stack by adding events to the event queue after the mmc.full_focus() call in the hook function. Do you think this will be a better approach?

Yeah I think that would be another reasonable way to do it if it makes more sense to you

@henrypinkard
Copy link
Member

I added some more description of hooks to the docs (#357). If you see any areas for further improvement, feel free to send a PR

@ieivanov
Copy link
Collaborator Author

ieivanov commented Feb 15, 2022

Thanks Henry, your feedback was helpful, sorry I didn't follow up earlier. My question was at what point is the image metadata saved. If I change the hardware in the post_hardware_hook_fn would that be reflected in the saved metadata?

P.S. I'll post here the solution I came up with

@henrypinkard
Copy link
Member

Yes I believe it will

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

No branches or pull requests

2 participants