-
Notifications
You must be signed in to change notification settings - Fork 112
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
Discussion of callback system in MMCore #164
Comments
I'm adding @ptbrown1729 and @AlexCoul to this conversation, they are the main group members in my lab working on control code. Primarily, I believe we land into the Python user group, although we do some C++ and Python/Java work. We are moving to unify our code into a single Napari-focused use case: One GUI widget per scope control module, where each widget interacts with external hardware and DAQ cards in a manner that often does not fit the "standard" micro-manager model. @ptbrown1729 has a fork of your napari-micromanager project that does this for setup and operation for a DAQ as master dual mode microscope. |
I agree with all of the above and can add that I think it will be difficult in the end to patch up some of the design limitations in MMCore from the higher-level Python/Java end with the wish to keep development cost surmountable. For example, being able to support simultaneous acquisition on two or more cameras/sensors will be pretty key for a lot of future technologies but currently, MMCore requires some hacks at the C++ level to overcome this. I'm sort of in a daily discussion with myself if what I'm doing makes sense at all. Especially with all the closed drivers and everything making smooth builds and maintenance wishful thinking for a distant future, versus just designing software for single hardware implementation and doing that very very well and high-performance level. But that is a discussion for another day. I do however strongly believe in what this thread tries to accomplish. |
I'm curious about both those hacks and that daily discussion. Perhaps open a new issue for those? Also as for the smooth builds (#86 (comment)) a question for @marktsuchida is are there ways we could be help move that forward? I think several people on this thread have an interest in improving the situation and I for one would be happy to try to help make it happen. |
I can't say that I don't feel the same sentiments as @tractatus pretty often. Focusing on notification/callback stuff for now (please feel free to create other issues -- an issue for multiple cameras appears to be missing even though we are well aware of the problems), I think there are some things that can be done in C++ that are worthwhile and may prolong the useful life of MMCore. I feel that the devil is in the details, though. Apart from the ones already discussed, what sorts of callbacks are you envisioning? It would help to hear what notification capabilities you feel are lacking, even if you're not sure what the concrete callback signals should be. (I can think of too many.) If it is only going to be a few more that are similar to the ones discussed, it's not hard to just tack on. Somewhat more can be achieved after what I would consider reasonable effort by refactoring the internals of MMCore to make it more modular but preserving its API (basically, take logic out of At some point, though, adding notifications to the existing behavior may no longer be sufficient for correct concurrency management. That is the point where things really start to get hard. None of our existing notifications (e.g. property changed) guarantee any specific concurrency behavior. They are fire-and-forget (nothing is guaranteed to wait for them to return), and are not guaranteed to be issued from any particular thread, although it wouldn't be hard to make them always fire from a dedicated thread. It just occurred to me that the just-proposed device-will-become-unavailable (#163) departs from such behavior, because it needs to guarantee that the device will stay available while the callback runs. This makes me wonder if we should already start organizing these into two separate categories (potentially-asynchronous notification vs synchronous callback). The decision might be better informed if we think about other notifications/callbacks we want to add soon. |
So when looking at #163 I noticed that for each callback I added there was already a Core logger that could be callbacksall the default role assignments mmCoreAndDevices/MMCore/MMCore.cpp Line 726 in ab2fc60
mmCoreAndDevices/MMCore/MMCore.cpp Line 872 in ab2fc60
device initliazation a callback per device and one for the final log statemnt: mmCoreAndDevices/MMCore/MMCore.cpp Lines 897 to 906 in ab2fc60
system cache updates mmCoreAndDevices/MMCore/MMCore.cpp Lines 965 to 974 in ab2fc60
waiting for a device mmCoreAndDevices/MMCore/MMCore.cpp Lines 1203 to 1230 in ab2fc60
setPosition mmCoreAndDevices/MMCore/MMCore.cpp Lines 1334 to 1341 in ab2fc60
stopping stage mmCoreAndDevices/MMCore/MMCore.cpp Lines 1607 to 1617 in ab2fc60
homing stages In particular if a downstream library intiates a mmCoreAndDevices/MMCore/MMCore.cpp Lines 1661 to 1679 in ab2fc60
setting origins mmCoreAndDevices/MMCore/MMCore.cpp Lines 1705 to 1718 in ab2fc60
snapImage mmCoreAndDevices/MMCore/MMCore.cpp Lines 2389 to 2397 in ab2fc60
imageSynchoList updated mmCoreAndDevices/MMCore/MMCore.cpp Line 2506 in ab2fc60
autoshutter set mmCoreAndDevices/MMCore/MMCore.cpp Lines 2468 to 2490 in ab2fc60
sequenceAcquistion all the life cycle events of sequence acquisition would be good for a GUI to know about. Again example of GUI is open and then user starts something from a script. mmCoreAndDevices/MMCore/MMCore.cpp Lines 2764 to 2767 in ab2fc60
circular buffer logs in a few places. Not super convicned that these need callbacks. But listing in the spirit of cataloging logger uses and I lost stream at occurance 73 of 126. Anyone feel free to edit to add more. |
I'm not so sure these logging lines are always a good proxy. It is not useful to know that the app set X (technically, the app already knows that); what you want is a notification that X changed, for any reason. (Which is why I mentioned that some refactoring of the code would help -- to provide code paths that are more unified.) But these broadly seem to break up into two categories: "configuration changes", and "misc device actions that are similar to property changed but not expressed as properties". There's a lot to say about each event, but I don't think it is that hard to implement most of these (quite a bit of work, but not enough to say never). I do think it is a good idea to do some refactoring first, and definitely we should come up with a way to issue notifications with less boilerplate. For the misc device actions, some warrant a callback from the device adapter, not just from inside MMCore, so that externally initiated actions can be reported where possible. The point that we need to think carefully about the timing/concurrency implications stands. For things like The system state cache is its own problem, because it is impossible to use it both correctly and efficiently. What would be better is a cache that allows invalidation of individual entries (so that they are fetched on the next update) but what we have is one where values are opportunistically updated on setting (which is not always correct) and on device notifications, with no way of telling if any of the entires are up to date. There is also the problem that only property values are cached (pity an everything-is-a-property approach was not taken in early MMDevice design). I slightly hesitate to add notifications that are tied to the current cache implementation, although it might not be that bad since a new implementation will probably need a new API anyway. Image synchro is an ancient feature that ought to be deprecated and removed entirely. |
@tractatus, I opened an issue concerning more native multi-camera support at #168, Very curious about your hacks. Also very motivated to get something done pretty soon. |
@nicost wow that is awesome! Ok I'll try to put together what I have sofar on my limited end of experimenting on a single system and ad to that issue. I know that both me and @kasasxav have a mutual interest in getting this off the ground. |
There has been some scattered discussion of whether new callbacks should added in a python wrapper or directly to the C++ core. I'd like to suggest using this issue as a place to centralize that and work out the future of potential new callbacks in MMCore.
My use case is that I want to interact with microscopes in the following way:
As far as I can tell this mixed methods approach means that in order to keep both the GUI and script up to date on the current state of harware/core state there will need to be a decent number of new signals introduced.
In a dream world it would be easy to add these to the C++ core as it would benefit all downstream users and be standardized. However, this brings a higher development cost than adding them to Python. That development cost is surmountable, but I think that @marktsuchida raised some important concerns in #150 (comment) and #150 (comment)
Before I go off and try to start implementing signals somewhere it would be nice to work out what the best approach would be. To that end I think some of the key questions are:
snap()
method #150:Downstream users (that I'm aware of):
Python: @tlambert03 @fdrgsp @ianhi @oeway
Python/Java: @henrypinkard
Java: All already watching this repo I believe :)
C/C++: @dpshepherd (I think c++?), @tractatus
The text was updated successfully, but these errors were encountered: