forked from ImSwitch/ImSwitch
-
Notifications
You must be signed in to change notification settings - Fork 18
Open
Description
Description:
It would be extremely useful to have a running Jupyter kernel inside ImSwitch so that we can inspect and interact with the current application context (e.g. managers, controllers, global variables) directly from a notebook/console while the app is running outside from ImSwitchClient via REST. Direct hardware access and processing abilites would be great to have!
This would allow:
- Debugging of live experiments by checking the state of managers
- Calling functions directly (e.g. stage moves, camera acquisition)
- Prototyping new analysis code without restarting the full app
Proposed approach:
- Use
ipykernel.embed.embed_kernelorIPKernelAppto start an in-process Jupyter kernel. - Inject
globals()(and importantly themoduleMainControllers,managers, etc.) into the kernel’s namespace so they are directly accessible. - Because
embed_kernel()is blocking, this needs to run in its own thread. Otherwise it conflicts with the main Qt loop (GUI mode) or thewhile Trueloop (headless mode).
Code sketch (inside applaunch.py):
import threading
try:
from ipykernel.embed import embed_kernel
except ImportError:
embed_kernel = None
def start_embedded_kernel(ns):
if embed_kernel is not None:
embed_kernel(local_ns=ns)
def launchApp(app, mainView, moduleMainControllers):
# ... existing code ...
# Start Jupyter kernel in background
ns = globals().copy()
ns.update({
"moduleMainControllers": moduleMainControllers,
# optionally inject managers here if available
})
threading.Thread(target=start_embedded_kernel, args=(ns,), daemon=True).start()
if IS_HEADLESS:
while True:
emit_queued()
# ... existing disk check logic ...
else:
if mainView is not None:
mainView.showMaximized()
mainView.show()
exitCode = app.exec_()Open questions:
- Where is the best injection point?
launchAppseems natural, but maybe aftermoduleMainControllersis fully initialized. - Should we expose only high-level managers (
StageManager,LaserManager, etc.) or all globals? - Security: embedding a kernel means anyone with access can execute arbitrary Python. Should we guard this behind a config flag?
- In headless mode, do we want the kernel loop to replace the infinite
while True, or run alongside it?
Next steps:
- Add a config option (
--with-kernel?) to enable/disable this feature. - Verify it works both in GUI and headless modes.
- Document how to connect (
jupyter console --existingor select kernel in JupyterLab).
Copilot
Metadata
Metadata
Assignees
Labels
No labels