-
Notifications
You must be signed in to change notification settings - Fork 27
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
The fourth dimension and the case of the missing slider #154
Comments
I hypothesised that the state at the end of the animation was the important thing, but no: adding |
woah what on earth - just to be clear: the sliders are there in the viewer, not there in the resulting animation but are there in viewer screenshots?! |
this is nuts |
I'm glad you agree 😂 but sad you're not all like "oh yeah I've seen this before and had a good lead on how to fix this but never got a chance to trying it". 😂 Yes your interpretation was correct. 🤯 |
at the Pacific community meeting, @andy-sweet pointed to this bit of code as a potential culprit: The if conditions are a bit, ahem, iffy, 😜 more specifically they are non-trivial, so it's worth checking whether there's some spurious reason there that the sliders are invisible in these circumstances. Regarding the script itself and the discrepancy between the animation and the screenshots — if I'm not mistaken @alisterburt, the first two screenshots are taken on the first pass, whereas the animation that happens at the end actually replays all of these things based on the past viewer state, so they aren't exactly happening simultaneously, but rather at the end of everything, is that correct? |
interesting - I have some time booked in with @katherine-hutchings next week so maybe we can dig into this together, this looks interesting for sure!
I'm not 100% what you've said is correct so I'll state what's happening: each |
Sure, that's fine, I don't think that contradicts what I said. What I meant is that in my script, I do, for example: # 1
viewer.dims.current_step = (9, 19, 15, 20)
animation.capture_keyframe(steps=10)
# 2
iio.imwrite('random.png', viewer.screenshot(canvas_only=False, flash=False))
# 3
viewer.dims.current_step = (9, 0, 15, 20)
animation.capture_keyframe(steps=20)
# [...]
# 4
animation.animate('random.mov', canvas_only=False, fps=10) So, in step 1, I set an attribute, Correct? |
correct, I'm with you :) |
Dang. Just stepped through it and it was saying all the right things. 😂 WEIRD!!! |
More info, sorry for the noise, but I could stop at any minute so I want to write things down. 😅 I wanted to see whether the issue was that the slider was getting hidden, or that the height of the slider space was getting reduced. Turns out it's the latter! In: I hardcoded the height to have space for two sliders, and then the sliders were in the video, and shown and hidden at the right times! random.movWeirdly, as happened when I was stepping through the code, if I print nsliders, it's always being set to the right number. 🤔 |
Ok, more weirdness (which you can also see in the video above, looking closely):
Before napari-animation works its magic: After napari-animation has messed with the viewer: So, there's something different about how napari-animation updates the viewer state, indeed hinted at by @alisterburt above: it updates all the dims attributes, not just those that have changed, and (this is then almost certainly a napari bug, not napari-animation) doing this actually results in some weird intermediate state that is somehow wonky. |
Ok, so the updating all the attributes is not the issue, the issue is that those attributes are updated in EventedModel with events blocked: And, notably, I ran the code with a breakpoint on this line, where the blocked events are supposed to all be emitted in a batch, and it was never called: So I'm wondering if there's a bug in the I also think it might not actually be necessary? If I delete the context manager, just update attributes willy-nilly and let the events fire when they may, (a) it has no measurable effect on performance (the EventedModel setattr itself checks for equality so won't emit events unnecessarily), (b) the sliders work! 🎉 Actually, the wonkiness is still there, but it happens even when just taking the screenshots (I added an extra I'd love to get the opinion of some EventedModel experts about whether that is the right approach here... CC @sofroniewn @tlambert03 @brisvag... |
Oh wow - excellent digging @jni ! I haven't looked at the old evented model code but this could be an excuse to update to the psygnal backed one inside napari... |
details/links? But this seems like a bigger lift than I want to do for this particular bug. 😂 Do we have a mix of things within napari already? Cos if not, I think I'd rather avoid it — we should convert the whole codebase in one go. At any rate, as far as I can tell, |
you can use |
@tlambert03 sure but then you lose the ability to "capture" the emissions and emit them all in a batch at the end... Right? |
Also, would you say that this use here was in fact intended to be a |
(Thank you for dropping by btw 😅 it is appreciated!) |
reading that code now, I would say that would be my expectation of what that code should do 😄 ... but I can't remember let me take a closer look at your example above |
alright... looks like this is an issue with event-loop driven things not having a chance to execute before the frame is captured. random.mov(side note: that has the side-effect of showing the viewer while rendering... which is probably undesirable in some cases, but I think that's gonna be the situation you're stuck in for a while, similar to how some of the napari tests only work if you use |
alternatively, you could place that call to processEvents upstream in napari at the beginning of |
FWIW, this was also a proposed solution for making In that case, we emit a napari event on the slicing thread and thus use I don't think the details here are quite the same (i.e. I don't think there's another thread), but my assumption was that most (all?) Qt events will always be enqueued to their associated event loop, so I'm not sure of another obvious fix to handle that generally. |
I thought we already did this!! 😂 |
I think these are the conditions for this bug to manifest:
In this scenario, the viewer should have 2 sliders at the start, then 1 at the end. But in fact it ends up with 1 at the start and 0 at the end.
Here's a reproducible example:
The iio.imwrites are there to show that viewer.screenshot is itself working fine. 😅
The result is:
random.mov
and the intermediate images:
The text was updated successfully, but these errors were encountered: