-
Notifications
You must be signed in to change notification settings - Fork 81
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
Add callback mechanism for GUI mode #301
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #301 +/- ##
==========================================
- Coverage 77.81% 77.48% -0.33%
==========================================
Files 16 17 +1
Lines 2010 2034 +24
==========================================
+ Hits 1564 1576 +12
- Misses 446 458 +12 ☔ View full report in Codecov by Sentry. |
15e8366
to
dbb930c
Compare
884c7df
to
3f0188b
Compare
Edit: This is no longer an issue with labeling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I'm excited about these changes @elevans!
I'm a bit wary about that new override
parameter on the initialization function, though - let's discuss below.
Otherwise, there is no way to access it from other threads. This may be useful for scenarios like napari-imagej, where access to Python scripting is available from threads other than the blocked one.
This is an internal variable, not intended as public API.
It doesn't need to be "ij_wrapper" or "ij_fixture". It's OK to be ij!
This test checks that functions registered via when_imagej_starts get called as part of imagej.init.
This commit adds section 5.2 to the "Convenience methods of PyImageJ" that describes how to use the when_image_starts callback mechanism.
This commit introduces a check to determine if the current running thread is the main thread. If True, then we continue to block interactive mode on macOS (it is not possible to share the main thread with GUI event loop needed for the ImageJ GUI). If False, then the current thread is *not* the main thread (e.g. a jaunched session) and interactive mode for macOS can proceed.
fda4992
to
d0eed46
Compare
Thanks @gselzer for your review! It made it sooo much better! I addressed all your comments. Ready to merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the new changes!
...unfortunately, I requested a couple new things 😅
src/imagej/__init__.py
Outdated
# Add function to the list of callbacks to invoke upon start_jvm(). | ||
global _init_callbacks | ||
_init_callbacks.append(f) | ||
if sj.jvm_started(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem like the right check, does it? Presumably, users would want to utilize an initialized ImageJ here. Is that always the case if the JVM is running? I'm assuming there's some period in between...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I lifted this from scyjava
but thinking more deeply about it, the right check should be the existence of the gateway
itself. So the check becomes:
global gateway
if gateway:
f(gateway)
I'll need to test this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we agreed that we will only have a gateway
attribute on the imagej
module created in GUI mode, this solution no longer works/makes sense. This method works as intended when called before initializing ImageJ in GUI mode. However, if ImageJ is already initialized and the main thread consumed by the event loop then it becomes impossible to call when_imagej_starts_()
, making any check of a pre-existing gateway
attribute pointless. As I see it, there is no good way to detect if an ImageJ has been initialized in addition to obtaining a handle on the gateway
to use with the desired callback. Thus, I decided to remove this commit and revert it back to just loading the callbacks into the _init_callbacks
global list.
Before I resolve this though, what do you think @gselzer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that makes sense too.
Use a more descriptive attribute name and value for when_imagej_starts() test.
This commit adds the pthread library loading exception to the logger and assumes that the current thread is the main thread if no pthread library is found.
Update
Update I wanted to preserve the original text (below) for this PR as its relevant to the goals (i.e. create a better experience for macOS users). With the awesome work that @ctrueden has done with
jaunch
we now have a way to actually supportinteractive
mode on macOS. This PR introduces the following new elements and also paves the way for interactive mode on macOS viajaunch
.This PR adds:
when_imagej_starts()
. This can enable some GUI related workflows on macOS (a kind of limited psuedo-interactive mode). See notebook 5 section5.2
for the relevant documentation. This callback mechanism is not compatible with napari.override
flag to the maininit
method. This flag will enable users/developers to bypass initialization checks/blocks we've put in place to stop unsupported/application breaking behavior -- mainlyinteractive
mode on macOS. To test interactive mode on macOS:jaunch
'sfiji.py
file. Add theoverride=True
flag toij = imagej.init(app_dir, mode="interactive")
on line 72../fiji-macos-universal -i --python
.Some other relevant information: Based on what I now understand about Python's threading system and some experimentation on macOS/Linux with
jaunch
, Python will always think its in a main thread. There is no way (from what I gather) to know if a particular Python instance was started with/in apthread
. Instead, threads that are spawned from an already running instance, say in a function that creates threads, are identified as "non-main" thread. This is obvious, but it would have been cool if there was a way to know about how the current instance was started.Original text
Until we can find a true interactive mode for macOS (see #298) this callback mechanism gives macOS users the ability to run their desired Python functions before the REPL is locked by the
AppHelper.runConsoleEventLoop()
.Here's how you register a callback with PyImageJ:
Unfortunately this callback strategy doesn't work with
napari
. Registering the callbacklambda: napari.Viewer()
results in this segfault: