Closed VolkerH closed 3 years ago
will take a look... can you tell me what coordinate_utils
is?
I added coordinate_utils.py
to the gist above. Basically just a few functions that read stage positions from a .txt
based metadata file and return them as a pd.DataFrame
.
I will also try and gut out the code to create a minimal reproducible example in the next half hour.
Oh, and total side note:
You can put viewer: "napari.viewer.Viewer"
in the decorated function signature to get the current napari viewer (rather than creating it in the function)
Oh, and total side note:
You can put
viewer: "napari.viewer.Viewer"
in the decorated function signature to get the current napari viewer (rather than creating it in the function)
I was just wondering about where to create the viewer. What is the significance of enclosing the type as a string there? This is some sort of Python construct that I have not previously encountered.
This error is rather weird, I haven't succeeded to get a minimal example there.
What is the significance of enclosing the type as a string there? This is some sort of Python construct that I have not previously encountered.
That's a lovely typing construct called a forward reference. It's optional (in that you can also use the non-string form) ... but it lets you annotate something as being of a certain type without actually having to import that thing. So these two have more or less the same result from a typing perspective:
from napari import Viewer
@magicgui
def func(viewer: Viewer): ...
from typing import TYPE_CHECKING
# the TYPE_CHECKING clause is also optional, but if you include it
# IDEs will be able to resolve your forward references
# and you can continue to not directly depend on them
if TYPE_CHECKING:
import napari
@magicgui
def func(viewer: 'napari.viewer.Viewer'): ...
Thanks! I like type annotations but I never dug that deep. They almost seem to be a whole language on top of Python in itself.
Regarding my original problem with this issue. I made some changes, including passing the existing viewer as suggested as well as docking the widget in napari:
https://gist.github.com/VolkerH/68235e3ed954bfd7c612ed29fb779546
This version works as intended and does not crash. I still don't know why the other one did. Maybe the presence of the separate floating Qt dialog caused some issues.
This version works as intended and does not crash.
huh, well I'd still like to figure out why the other one did too. what changed here outside of passing the viewer? If I run the original updated gist, should it crash for me?
Well, to reproduce the original you probably need the dataset that I used. Let me know if you want it and I will send you a dropbox link (can't share it here).
I tried a few things to create a small reproducible example, such as replacing the image loading with random array generation but I was not able to make it crash in the same manner.
actually, @VolkerH ... looking at this again, there's another thing I should have mentioned about magicgui and napari... If you want the output of a magicgui function to be added to the napari viewer, the "most tested" way is to use a special return annotation in your function. this might let you avoid the viewer object and your showfiles function altogether:
# untested ... but here's the basic idea
@magicgui(call_button="Show Mosaic", auto_call=False)
def mosaic_well(
settingsfile: Path,
viewer: "napari.viewer.Viewer",
subsamplefactor: int = 2,
channel: int = 0,
directionx: int = 1,
directiony: int = 1,
crop: int = 12,
do_transpose: bool = True,
) -> "napari.types.LayerData":
...
# where layer_data is a list of tuples,
# and each tuple has up to three members: (data, {metadata}, 'layer_type')
layer_data = []
for name, coord in zip(files, coords_numpy):
translate = ([coord[0] / subsample, coord[1] / subsample],)
layer_data.append((getimage(name), {"translate": translate}))
layer_data.append(
(coords_numpy / subsample, {"size": 30, "face_color": "red"}, "points")
)
return layer_data
The general idea here is that programs like napari can register both visual representations and behavior for a specific type. In this case, napari has registered that "if a function is annotated with a return type of napari.types.LayerData
, then add each of the layerdata tuples to whatever viewer that magicgui widget has been added to ...
there are more of these "special" types (like napari.types.ImageData
... which can just return a np.array) needs better docs, sorry
Thanks Talley, ... even more magic ..., will give that a go.
@VolkerH, let me know if you'd like to keep this open. Sounds like you have a fix by not directly creating and working with the viewer inside the decorated function right?
Sorry Talley, I lost track. I'll close it for now as I cannot reproduce with a minimal example. The issue with hidden magic is sometimes that it is a bit harder to debug for non-magicians. (not a criticism of magicgui, I love it, more an apology for not providing more detailed info on this one).
no apology needed. the napari-specific magic is woefully lacking in documentation. "magic" that performs a series of commonly performed tasks without much effort is awesome. "magic" that does invisible shit that you have no idea about is useless! :joy: I'll write something up soon.
feel free to reopen this if you find a MRE
Describe the bug
I have some sample code here
https://gist.github.com/VolkerH/d732ab350113deb347fe4beafd778993
This is not a minimally reproducible example yet.
If I do not decorate
mosaic_well(...)
with@magicgui
everything runs fine. A mosaic is loaded, the tiles are displayed and the anchor points for each tile are plotted. If I do decorate withmagicgui
the code crashes at this line when adding the points:``pts = viewer.add_points(coords_numpy / subsample, size=10, face_color="red")
I will include the traceback further down.Removing the
viewer.add_points
line prevents the crashing and I can view the mosaic. I can't make sense of it.To Reproduce See above.
Expected behavior Decorating the function shoud not cause shader compilation errors.
Environment (please complete the following information):
OpenGL:
Screens:
Plugins:
Traceback that I observe with decorator: