-
Notifications
You must be signed in to change notification settings - Fork 50
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
Consider/brainstorm about a "Unique" type modifier for inputs #561
Comments
the thing that makes this a bit tricky in my mind (and which makes me slightly hesitant to offer it as a feature) is the problem of the "scope" of the uniqueness. For example, in affinder, the goal is simple enough if you consider a single affinder widget (which has two comboboxes) in a single napari viewer... but what if you dropped in another affinder widget? i would assume those options only need to be unique within a given affinder widget instance, within a single viewer. Offering unique options means having a set of all possible options, and then narrowing based on some awareness of the other widgets that are also monitoring that set of options... and that's the bit that seems like it would have a number of very valid permutations, and which i'd rather not be in the business of managing. here's a very rough, currently broken sketch: from typing import NewType
from magicgui import magicgui, register_type
import napari
import napari.layers
from napari.utils._magicgui import find_viewer_ancestor
def get_unique_shapes(gui):
if not gui.parent or (viewer := find_viewer_ancestor(gui)) is None:
return []
# get all available layer options
all_shapes = (
layer
for layer in viewer.layers
if isinstance(layer, napari.layers.Shapes)
)
# get values claimed by other widgets
# this is an ugly hack to figure out the other magicgui widgets in the same widget
# it uses both the Qt and magicgui APIs... look into a better way
other_values = {
w._magic_widget.value
for w in gui.parent.parent().children()
if hasattr(w, '_magic_widget')
and w._magic_widget is not gui
}
# return all options that are not claimed by other widgets
return [layer for layer in all_shapes if layer not in other_values]
UniqueShapes = NewType('UniqueShapes', napari.layers.Shapes)
register_type(UniqueShapes, choices=get_unique_shapes)
@magicgui
def widget(layer1: UniqueShapes, layer2: UniqueShapes):
...
viewer = napari.Viewer()
viewer.window.add_dock_widget(widget)
viewer.layers.events.inserted.connect(widget.reset_choices)
viewer.layers.events.removed.connect(widget.reset_choices)
# need something like this too, but it's causing recursion errors at the moment
widget.layer1.changed.connect(widget.layer2.reset_choices)
widget.layer2.changed.connect(widget.layer1.reset_choices)
napari.run() I say currently broken because there's a still a recursion error when you try to update the options in the other widgets whenever one of the widgets changes its value. Anyway, that gives you a sense for how it could be done, and also how many tricky gotchas there might be in a successful implementation |
This issue has been mentioned on Image.sc Forum. There might be relevant details there: https://forum.image.sc/t/napari-magic-factory-image-inputs/97225/2 |
In some situations, values in an API are of the same type but can't have the same value. Particularly, any time you have a function to compare or match two different objects.
In this case, you want the same widget for the two values in the generated UI but you want to prevent the same value from being selected. The motivating example is choosing images for registration in affinder, but there's certainly others, such as choosing two segmentations (e.g. automatic and ground truth) to compute an accuracy score, or various kinds of "image math".
This can be done in user space as suggested by @tlambert03 (example at jni/affinder#63), but it seems useful enough to support more generally. I don't really know how I would go about it though so I'm hoping you can write a sketch of it here @tlambert03? 🙏
The text was updated successfully, but these errors were encountered: