I’m trying to get a layout where one slice view serves as “target” and other slice views serve as “controls”. So, I want to make the target slice (“intersection”) visible in the controls, but not vice versa, and of course I don’t want the control slices visible in each other. In some situations, I also don’t want target slice visible in a specific control slice.
By reading the documentation, it looked like I could have all the control I wanted by using two different methods on the SliceDisplayNodes:
SetVisibility2D(): Set the 2D visibility of the display node.
would control if a slice can be shown in other slices
SetIntersectingSlicesVisibility(): Toggles visibility of intersections of other slices in the slice viewer.
would control if the slice viewer shows the other slice intersections
So I thought the intersection would only be visible if both “sides”, so to speak, are on. But it didn’t quite work this way; playing with these flags caused all sorts of unwanted effects. I finally cheked the source, and found (vtkMRMLSliceDisplayNode.h, line 53):
The function seems to work exactly the way it is documented.
The text is
“Toggles visibility of intersections of other slices in the slice viewer”
which means that intersections of the other slices (i.e. the colored lines) will appear in the slice viewer, which is the slice view that uses the display node in question. Seems quite unambiguous to me.
Assume the standard view. I want to show the intersection of the red slice in the green slice, and no other intersections.
After reading the documentation, I thought I’d be able to achieve this with:
lm = slicer.app.layoutManager()
r, y, g = (
lm.sliceWidget(t).sliceLogic().GetSliceDisplayNode()
for t in ("Red", "Yellow", "Green")
)
g.IntersectingSlicesVisibilityOn()
r.Visibility2DOn()
But that gives me (after making sure all slices are updated)
According to the documentation, I should have seen no intersections in the yellow slice, no matter what happens in the red and green. And in fact, there is no way for me to say “Red, be visible in others but don’t show others; Green, show others in yourself but be invisible to others”.
The piece of code I quoted (and you pointed to as well) shows that, in fact, there is no separation between “am I visible in other slices” and “am I showing other slices” – the interface that is documented to do the latter, does the former.
The question was – is this effect intended? If so, the doc is wrong. If not, it is the code.
The first 95% of your description stands. There is no “two-sided” definition. The only thing we can turn on and off is whether “the intersections of the other slices in this slice in the layout view group are visible” or not.
This part, however, I don’t understand. Do you agree with my previous answer that the documentation of the Get/SetIntersectingSlicesVisibility function is correct?
The documentation, as far as I can get it, and as far as I read your interpretation of it as well, says that when, in my example above, y.GetSliceIntersectionVisibility() returns 0 – that is, when SliceIntersctionVisibility is off for the yellow slice – then you should see no intersections of other slices in the yellow slice.
What actually happens, as exemplified above, is the reverse. It is the intersections of the yellow slice that are hidden elsewhere.
I think that the description “Toggles visibility of intersections of other slices in the slice viewer” is quite straightforward. I explained it in more detail above. If this bothers you and want to spend some time please issue a PR suggesting a different description.
When the display node related to a slice view has SliceIntersectionVisibility off – should I, or shouldn’t I, see intersections of other slices in this view?
(I guess the question is the meaning of “the intersections of the other slices in this slice”. I understand this to mean – the lines representing the other slices in the view for this one. I fail to see how one understands the converse).
You’re right. I was convinced that it works as described, but I just tried it myself and it works the opposite way, it controls the visibility of the slice intersection of the current slice in the other slice views of the layout view group. I think I never realized this because I always use it on all the slices, and not individually.
At this point I’d update the documentation because many other functions rely on this one.
Here’s a snippet that only turns it on for the red slice:
(the example, of course turns on only the red slice’s intersections – but still turns it on in both the green and the yellow slices, so it’s not a solution for my use case)
My only idea now is to play with the layout view groups, but I don’t have much faith in that, because I think you can either show the intersection in all slice views in the same group, and nothing in other gropus (this can be confirmed by adding a new layout by the XML text, which defines different view groups).
If you have a suggestion for a better way to define slice intersection visibilities, we’re happy to discuss it.
This turned out to be good enough for me – it’s not full control, but it’s enough if you only want to show the intersections of one slice. And it turns out you don’t really need to touch XML, because vtkMRMLSliceNode inherits a GetViewGroup() and a SetViewGroup() from vtkMRMLAbstractViewNode, which let you control the groups dynamically for existing slice views. Putting a slice in a separate view group has some other effects – in my case, they don’t matter, and they may not matter for other users as well. The effects are explained in the documentation for SetViewGroup().
To summarize, if you want to show the intersection of the Red slice in the Green slice and not in the Yellow:
lm = slicer.app.layoutManager()
rsw, gsw, ysw = [lm.sliceWidget(color) for color in ("Red", "Green", "Yellow")]
# Make Red slice's intersection line visible in other slices
rsd = rsw.sliceLogic().GetSliceDisplayNode()
rsd.SetSliceIntersectionVisibility(True)
# To work with view groups, we need the SliceNode's
rsn, gsn, ysn = [sw.mrmlSliceNode() for sw in (rsw, gsw, ysw)]
# Assume Red and Green are in the default view group
assert rsn.GetViewGroup() == gsn.GetViewGroup() == 0
# Set Yellow to a separate group
ysn.SetViewGroup(1)
# Make sure the slices are updated, otherwise the line appearance is delayed
for sn in (rsn, gsn, ysn): sn.Modified()