Synchronize display scale across slice viewers

Hi,
is there a quick way to synchronize the zoom factor across slice viewers?
Thanks
Stephan

Yes. Long-click on slice view link icon and enable hot-linking. Maybe it only synchronizes views that have the same orientation. If this is the case then you may need to write a few-line Python script that observes zoom factor changes in slice views and adjusts zoom factor in all the others.

1 Like

Hi Andras,

Yes, that is correct.

Unfortunately, this is literally the first time ever I opened the Python interactor. But at least, some googling brought me this far, and it does what I want it to

redSlice = slicer.app.layoutManager().sliceWidget('Red').mrmlSliceNode()
yellowSlice = slicer.app.layoutManager().sliceWidget('Yellow').mrmlSliceNode()

redFOV = redSlice.GetFieldOfView()
yellowSlice.SetFieldOfView(redFOV[0], redFOV[1], redFOV[2])

However, it would be nice to not always have to call the zoom alignment manually. Is there some zoom change event to hook an observer to (in vtkCommand I could not find something that looked very promising, but maybe I just missed it)?

Thank you
Stephan

Nice work! I’ve extended your example with slice node observers, which update field of view in all other slice nodes automatically when a slice node is changed: see complete script here.

2 Likes

Great, thank you @lassoan . That’s exactly what I was looking for.

I just added a tiny bit of additional functionality, namely to toggle zoomSync on and off.

slicer.updatingSliceNodes = False
slicer.zoomSync = False

slicer.sliceNodes = [slicer.app.layoutManager().sliceWidget(viewName).mrmlSliceNode()
    for viewName in slicer.app.layoutManager().sliceViewNames()]

def sliceModified(caller, event):
    if slicer.updatingSliceNodes:
        # prevent infinite loop of slice node updates triggering slice node updates
        return
    slicer.updatingSliceNodes = True
    fov = caller.GetFieldOfView()
    for sliceNode in slicer.sliceNodes:
        if sliceNode != caller:
            sliceNode.SetFieldOfView(*fov)
    slicer.updatingSliceNodes = False

def toggleZoomSync():
    if slicer.zoomSync: 
        # zoom sync is on already, therefore observer function is alread hooked, should be unhooked
        for sliceNode in slicer.sliceNodes:
            sliceNode.RemoveObserver(sliceNode.zoomChangeObserverTag)
        slicer.zoomSync = False
    else: 
        # zoom sync is off --> toogle to on (register observer function)
        for sliceNode in slicer.sliceNodes:
            sliceNode.zoomChangeObserverTag = sliceNode.AddObserver(vtk.vtkCommand.ModifiedEvent, sliceModified)
        slicer.zoomSync = True

toggleZoomSync()

After running this code snippet once, calls to

toggleZoomSync()

toggle slice zoom synchronization on/off.

1 Like