Skip to content
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

Plugin System for ImSwitch #164

Open
beniroquai opened this issue Jun 3, 2023 · 28 comments
Open

Plugin System for ImSwitch #164

beniroquai opened this issue Jun 3, 2023 · 28 comments

Comments

@beniroquai
Copy link
Collaborator

Idea

With the creation of the ImSwitch organization, we came up with the idea of separating the core from external hardware features. For this, it would be interesting to think of a plugin system, where additional cameras would be installable by e.g. a pip install able package. I have found a huge different variety of ways how to do it. Folks from the Openflexure microscope use extensions, the octoprint community has a very nice system that integrates cookie-cutter templates and hooks. All very fancy.

After going through the sensitive sections of the imswitch code, I thought the most simple version would be the linking of new hardware modules into the dedicated package paths inside the imswitch root folders. They would be loaded at startup anyway, so no need of complicated registration methods as it is typically done in these plugin systems. This would require to:

  1. identify the installation path of imswitch
  2. place managers, controllers, widgets in the corresponding folders
  3. add the "hooks" in the setup json
    the uninstallation of the pip package would need to remove any links from the imswitch installation

Pro:

  • simple
  • no change in the current code from ImSwitch side

Contra:

  • too simple?
  • ImSwitch Version vs. Plugin Version?
  • Git issue with new files that would need to be added to the gitignore
  • ...

I wanted to start the discussion, perhaps you have better ideas! :-)
(CC: @jacopoabramo @kasasxav )

Resources

https://gitlab.com/openflexure/openflexure-microscope-server/-/issues/1
https://eli.thegreenplace.net/2012/08/07/fundamental-concepts-of-plugin-infrastructures
https://github.com/OctoPrint/cookiecutter-octoprint-plugin
https://docs.octoprint.org/en/master/plugins/hooks.html#general-concepts

@untzag
Copy link
Contributor

untzag commented Jun 4, 2023

Consider happi [1] and entrypoints [2]. My two cents as an outsider. Might even be able to get compatibility across package ecosystems...

[1] https://pypi.org/project/happi/
[2] https://packaging.python.org/en/latest/specifications/entry-points/

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 4, 2023

Hi @beniroquai ,

Be careful that it still is compatible with the other efforts of developing ImSwitch. I think this plugin structure will go well with openUC2 but not sure if it aligns as much with other efforts in, for example, super-resolution microscopy. Maybe having both plugin structure but without removing the structure as it is now could work. But probably it would be nice to include people such as @fbalzarotti , @nornil , @GuillaumeMinet in the conversation so that they also agree about this new platform as well (since it will definitely affect everyone).

Best,
Xavier.

@beniroquai
Copy link
Collaborator Author

beniroquai commented Jun 4, 2023

Certainly. The whole discussion would be centered around compatibility. I think the way it is right now is not 100% ideal. It would be nice to have an always same core and addable plugins. Then we can split UC2 and all other individual implementations much better. I guess one could have a pip installable package for everything and ship that one. My guess is that we don't need any fancy discovery mechanism since imswitch uses hardcoded package links from the setup.json.

My implementation example so far relies on an additional keyword e.g. a camera inside the setup description that refers to the realization of an external plugin/package. Then the loading path for the package will get altered. I'm still experimenting. Would be nice to have a chat about his next week @jacopoabramo
Perhaps @RainerHeintzmann has some experience?
Napari makes heavy use of this autodiscovery from python setuptools, but I guess this is overkill here..

Thanks @untzag, I'll have a look at the happi examples. What exactly is this software doing? Wasn't clear to me ;-)

@jacopoabramo
Copy link
Collaborator

Hey everyone, sorry for the late reply.

@kasasxav I think the goal here is to put a fixed point on the main features of ImSwitch and make a freeze on what it goes in terms of controller support. Pushing new devices into the main repository is still something I reccomend, but other computational features/widget added as plugins would:

  • encourage a more pro-active development from the community, removing the "scary" part of having to understand how deeply a software works;
  • relax the stress on adding new features in the main repo, giving time to focus on maintenance/upgrade tasks.

napari in itself is a successfull example in how this policy works well with an open-source driven development. That being said you're absolutely right and another point of discussion is to finally merge all the efforts that have been done so far into the main repository - as you know we're trying to go into that direction but it takes time to synchronize efforts :)

@beniroquai I agree that the discovery mechanism implemented in napari is overkill for my taste, but as I mentioned before adding device control as a plugin possibility is something I would not reccomend - mostly due to the fact that other people may have similar ideas and end-up replicating same concepts differently. The widget is another story: it's a more relaxed concept and separated from the device layer.

I didn't have time to siff through all the links because I'm in a conference this week, I'll try to read all of them between pauses :)

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 6, 2023

Thank you @jacopoabramo @beniroquai , I think as long as it is backwards compatible it will be nice to take the approach. I'm curious how it turns out :) I like the idea of having in the json file the manager name either directly in the repo or using external packages as @beniroquai mentioned! I agree that it's good to start with the device layer and see how it goes.

I remember mentioning this to a CS professor and he told me that when you have a project in the beginning is good to have it all in the same repo so you can have more control over how it is implemented (necessary tests, mantainance, etc), and once you start relying on external sources or plugins it becomes a bit hard since you need a certain structure in how this classes should be done and make sure that people follow that, so it might be a bit hard with widgets.

I agree though that right now the device layer feels totally as a bottleneck and something that at some point won't be sustainable to have many different drivers in the same repo - ideally would be nice to have something external.

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 6, 2023

I think the main point is that when you make changes in the architecture or so on it is clear that it will still work for the people that don't need this feature, and then if everyone agrees that it works better the new way then potentially changing it. But for that is important that people won't be negatively affected by it.

@jacopoabramo
Copy link
Collaborator

@kasasxav where would be a good insertion point to manage imswitch plugins? I do not have enough in-depth knowledge of ImSwitch initialization sequence to make an educated guess, and some pointers on where to start thinking about where to put the code would be nice.

@kasasxav
Copy link
Collaborator

To be honest I think it's a bit hard to think about it.

I think the since in the setup info there is the managerName parameter, one could have a managerName called external and then as managerProperties you can have the PyPI package. So then you make a manager that imports a package from another repo. And then you can have a general function called: callFunction(func) so that you call the function func inside the external package, so that would be general for everything.

The problem is that this external manager should have the same functions as the ones inside ImSwitch, so it has to match the exact same classes and stuff, which is a bit hard.

In general I think it's going to be something quite hard to do and mantain, even if the idea is to make it easier for people.

@jacopoabramo
Copy link
Collaborator

Hmm I don't think putting the concept of "Manager" (which for us, or at least for how I've come up to understand it in the ImSwitch vocabulary, means a generic interface to a device) together with a plugin makes sense. The implementation of this layer, to me, still needs to be integrated by pull requests as we did so far.

For how I've imagined this system, plugins would be integrated into ImSwitch by sharing the communication channel in the presenter and by having a dedicated tab into the GUI. So something like this:

imswitch-plugin (1)

Of course, we can still use the configuration file in order to load only the plugins that are requested. Wether that these should be automatically installed via pip in case people don't want to go through the hassle of manually installing these plugins (and imagining the average user it's not even something too far fetched...), it can be discussed. Do you see what I mean?

@kasasxav
Copy link
Collaborator

I meant more how to do plugins for hardware devices, not for Widgets. But yes I guess this could be an idea.
I don't know how from there you would create and integrate the widgets in ImSwitch, I think you still need to incorporate it in the view and stuff, as it is it seems a bit complicated to me.

@jacopoabramo
Copy link
Collaborator

Hmmm what do you mean plugins for hardware devices?

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 12, 2023

I mean to me it's not that hard to do Widgets in ImSwitch. You just need to do a widget and its controller, and I think that would be hard to do as a plugin. Do you want to do only the widget or also the controller? And the controller feels hard to do externally since it needs to connect with all the other layers of ImSwitch. And how do you test something that is so connected to the other layers of ImSwitch outside of ImSwitch? For example if a widget controls a laser device, how do you do that without having the config file of ImSwitch and how do you test that in an isolated way?

I thought you meant that you can give support to a hardware device using an external repo, so to do the manager outside of ImSwitch. Since you said about the preassure of adding new devices I thought you meant that.

And if you only do the widget as a plugin, each widget needs to have a widgetController so you would need to create both an external plugin and a widgetController inside ImSwitch. Which I think it's harder than doing both in ImSwitch directly.

In my opinion simplicity is over-rated, sometimes for people to develop software you need to know how the architecture of it works, it's also what is giving other things such as robustness and modularity. And here the level of work is the same if you do externally or internally, in my opinion. And the difficulty of mantaining a plugin system and to make sure that is well connected inside ImSwitch + that people develop and test plugins in the right way, to me makes it not worth it.

P.S: I think because benedict said " I thought the most simple version would be the linking of new hardware modules into the dedicated package paths inside the imswitch root folders" that then what you wanted to do as plugins were the hardware models (managers)

@beniroquai
Copy link
Collaborator Author

I like that quote:
In my opinion simplicity is over-rated :D
Agree! Perhaps we can learn from other software's modularity and what may belong to the core and what not and how you can extend stuff. Having a look at micro manager of the octoprint may be of help?

I have started playing with external modules in imswitch. I think in principle it's possible and straightforward to implement for an experienced programmer. What I did is indeed add the keyword external to the JSON for a given manager. This will change the import path for the manager. The next challenge would, of course, be the accessibility of the active imswitch instance inside the external module (e.g. signals and stuff). I didn't have a further look yet, but will work on it "soon". Liked doable, yet reasonably complicated and modular to me.

Relevant changes:
openUC2@833c551

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 12, 2023

Yes sorry because it's a super strong claim to make haha. I think simplicity is very important but I mean that I think there is other things that are important too.

I think maybe it can help to understand why it is hard for people to implement widgets. Is it that they don't know what to change? Maybe with more documentation will help. Or maybe it is also because apart from widget and widgetController there are a few more classes to change (like the mainView), then maybe it could help to have some automatic way of adding those lines? So that's a bit my way of thinking, from the demand of the people using the software in the moment, what problems they have and what can we change that requires the minimum change possible so that it can solve the problem. Because doing big architecture changes for example could bring more problems. I know the architecture chosen needs people to invest some time on it but I think it also brings other benefits that are worth it, especially for certain microscopy techniques that have higher requirements.

I do think that the external managers could be quite helpful though, since in theory the device managers are only controlled through the masterController and they don't have knowledge of the controller so they shouldn't need the rest of ImSwitch right? And there I see a clear benefit that I feel almost everyone needs to implement new managers for different devices, so it feels hard to keep everything in the main repo and mantain it. This way maybe it could be more helpful to use external device layers from other software initiatives? The only thing though is to make sure that the devices are tested and implement the right functions that each of the manager types need. There it could be that there is some compatibility problem and then ImSwitch crashes so it would be harder to debug problems :P (then to make sure that the error messages are clear even when the error is from the external module etc.)

@jacopoabramo
Copy link
Collaborator

jacopoabramo commented Jun 13, 2023

@kasasxav in regards to the quote about simplicity I completely agree with you - I would prefer a robust, even if a little more complicated solution, as long as it gets the job done and it doesn't cause future hassles.

Unfortunately to make it "appealing" to the community I realized that most of the community itself is not really interested in a more structured solution but towards an approach that goes on the same lines of "as long as it works...", and so they tend to favor simpler solutions or already pre-existing onces - or ones that are documented.

Especially in the academic field I often encountered (and maybe this is my bias, in which case I may have to rethink my opinions about this) that that there's a lot of rush to reach to an answer to a question somebody asked, but there's no rush to provide the maintaned instruments to replicate that same answer.

I've seen this a lot in papers were the instruments were sometimes barely mentioned, with no reference to a software used to control these instruments (so most probably custom-made solutions). I hate this way of thinking, but trying to change the opinion of an entire community is unfortunately a battle against windmills.

What you did say I think it's the best solution to this problem: documentation, documentation, documentation. If the architecture is well documented, if relevant access points to make a plugin the way I initially inteded is well explained and there are is at least one tutorial for all the imagined use cases, people will definetely be encouraged to use it. What's good is also to start having a showcase of all of this stuff also in forums like Image.sc and so forth - it's definetely nice publicity.

I can see your point related to why people would be more interested in having a quick external access point for the devices with an externalManager, but I've been checking around and there's a lot of request of custom widgets as well for making it TRULY general-purpouse. The unfortunate thing about this field is that everybody needs something different, that's why Micro-Manager made it work also by using plugins.

As for the architectural changes, I don't think that the system I suggested would imply to change the architecture that much because in the end what you actually do is exposing the communicationChannel in order to give access to a custom controller to all the signals coming from the other layers. The challenging part maybe would be to add the widget in the main viewer... but maybe I'm not considering something related to the architecture that you know better than me?

@fbalzarotti since you're also working on your own separate fork, could you please chime in? I'm curious of what your experience with customizing ImSwitch is at this point. I think it should probably be a point of a more involved discussion with other people as well.

@jacopoabramo
Copy link
Collaborator

Oh, by the way, I am a bit hesitant to making the externalManager a thing because in the far, far future I'm envisioning a different language for the device layer. I would keep python for the viewer/presenter layers, but I would probably go as far as having a compiled language for the devices and having python bindings as a thin layer to communicate with the other layers. Either C++ or even Rust, which I think it's a choice more cohesive with the current technological standard. We'd have to take a lesson from the Micro-Manager device layer to realize something simpler, but there's no doubt in my mind that speeding the acquisition from cameras (which is the critical point), and having proper multithreading support, can only be achieved through this. Unless we want to use JPython or whatever interpreter supports multithreading :p

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 13, 2023

Sounds good the device layer thoughts.

I agree that there is a big preassure to have software that is magic and just plug-and-play, and that if you want to have a big community it is important to work in that direction. But do you want ImSwitch to be that? In my opinion it is also ok to have a community of people that really need it for their use-cases, and if you demonstrate applications that would only be possible thanks to ImSwitch and pinpoint why the architecture is beneficial this is also very valuable research as well. I think @fbalzarotti has always been very happy about the architecture for Minflux. But definitely he will be able to provide feedback in what to improve :)

Just depends on where you want to drive this. It is important to defind here what is the goal? But I would say if you want to grow it is important then to ensure that it is sustainable, and that the changes you and other people do will be able to be kept even after they potentially finish their academic positions etc. Growth always comes at a price and you need the infrastructure for that.

What I mean is that all the signals from the widgets need to be connected to a Widget controller. For example LaserWidget, LaserController. Which means if you have a plugin for the ABCWidget, you will need to connect these signals to an ABCController. And this controller needs to have access to the presenter and model layers of ImSwitch, so it is not possible to test it as an isolated entity from ImSwitch. For example, when calling self._master.detectorsManager from a WidgetController.

@jacopoabramo
Copy link
Collaborator

@kasasxav I agree with you, maybe right now ImSwitch is not in the correct point in its lifetime to discuss the possibility of implementing a plugin system and we should spend time in solidifying documentation and merging the work from other forks (which I think it's a critical point). But we can keep the issue open in order to have some discussion going on, you never know

@beniroquai
Copy link
Collaborator Author

beniroquai commented Jun 14, 2023 via email

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 14, 2023

Is it? I mean sometimes we take that for granted, we make a tool and the next step is to conqueer the world and everyone has to use it. If that is the goal, I totally respect that and it can be a very nice one.

To me, it was never my goal. My motivation was to create an open-source tool that people could use, and it was totally fine if I had 5 users or if I had 500. I have always been very aware that I didn't have the capacity to mantain a super big open-source community and I also didn't feel it was my motivation. The question is: do you have now the capacity to do it? Because what I see is that everyone develops ImSwitch for their research questions, but if you want to scalate something that itself requires a lot of work and resources. So then there is a lot of thinking in who is going to do that and how etc. And then, is that going to be the long-term goal? Or are people going to drop after 5 years? :)

This is very personal but for me, innovation is always driven by need. With ImSwitch I saw a clear need in our lab and others, and then I developed a solution. I don't want to push it to people if maybe they can use something else, that's ok. I just want to make sure that the people using it get the best of it and that it can enable research in the labs that it is being used. And already that is a lot of work too. Another of my ideas is that growth has to be supported by sustainability and a good base. I prefer to grow slowly but consistently and make people happy, than changing everything and grow super fast but then things becoming a mess.

I mean now for me I will move on from this project so it is up to the people left to decide how you want to drive it :) But I have been involved in this thread just to maybe give my perspective on the project, and also to question this common trend of doing an open-source tool that fits all, super simple to use and that if you spend more than 2 days to understand it people will find something else.

@jacopoabramo
Copy link
Collaborator

My 2 cents on why I want ImSwitch to succeed: I do indeed want something along the lines of what @beniroquai suggests, but I want to do this by breaking the pattern of rushing to development without proper thinking of what will happen in 10 years on the technology perspective. Quoting myself:

Unfortunately to make it "appealing" to the community I realized that most of the community itself is not really interested in a more structured solution but towards an approach that goes on the same lines of "as long as it works...", and so they tend to favor simpler solutions or already pre-existing onces - or ones that are documented.

Especially in the academic field I often encountered (and maybe this is my bias, in which case I may have to rethink my opinions about this) that that there's a lot of rush to reach to an answer to a question somebody asked, but there's no rush to provide the maintaned instruments to replicate that same answer.

I've seen this a lot in papers were the instruments were sometimes barely mentioned, with no reference to a software used to control these instruments (so most probably custom-made solutions). I hate this way of thinking, but trying to change the opinion of an entire community is unfortunately a battle against windmills.

Whenever I go around and talk to people during coffee breaks, conferences, seminars, whatever it is, there's always this lingering uncomfortable feeling that whenever you have a new idea for an instrument you have to "reinvent the wheel" to control it. And often this affects the work of PhD students who are not interested in programming but they become forced to do so because of this necessity. I've seen this first hand in a project I worked for a couple of months involving a software from a company developed by a sequence of PhD students in LabView and it was just ... impossible to use.

The way I see it, ImSwitch does have a lot of potential to break this tradition, but I definetely agree with @kasasxav on this:

I prefer to grow slowly but consistently and make people happy, than changing everything and grow super fast but then things becoming a mess.

So yeah, my goal is definetely to make a "one software to rule them all", if you will. But it must be done with the proper pacing and enstablishing ground rules for development by taking into account past experiences from other open-source projects, learn from them, taking the good things and trying to avoid the bad things.

@kasasxav
Copy link
Collaborator

kasasxav commented Jun 14, 2023

I think that sounds very good, and it makes me happy that you see ImSwitch useful for the community :)
As long as you reflect over it in the meetings and understand the challenges and do it at a good pace I think whatever you decide will be a good path. I think it's nice to have a long-term goal, definitely if the paper starts to get more cited and the repo used, there are academic articles about science where people have used it, etc, then people will also get more motivation to use it as well. It will take some time but I think it's a nice goal, but to reach it is good to also think about the process and go one step at a time :) I also agree that reducing the entry bareer is an important factor then.

Now that you say I think in the beginning that was my motivation too haha, I think then I realized how hard it is to sustain even having 5 users and started to have some doubts about it xD But don't let my pessimism stop you haha. I think ImSwitch itself has the potential to go there, that I strongly believe, I just realized that there is so many more factors involved.

@jacopoabramo
Copy link
Collaborator

jacopoabramo commented Jun 14, 2023

Now that you say I think in the beginning that was my motivation too haha, I think then I realized how hard it is to sustain even having 5 users and started to have some doubts about it xD But don't let my pessimism stop you haha

Nah I've also started with the same intention, it's just that at some point one just wants to finish the PhD project and go on their merry way :P and is totally legit. Me and @beniroquai are in a position where we can capitalize on the work you already did and use it as a strong codebase, and like I said: it takes time to get people involved.

And not gonna lie, we just need to survive the summer at this point - conferences, vacations, that kind of stuff.

@kasasxav
Copy link
Collaborator

I mean it was not so much about the personal situation but about the multiple factors involved in scalating a software solution that have to be taken into consideration that I didn't predict in the beginning, and the infrastructure needed. I was also looking for many different architectural changes so that it would be easier and more people would join, but then I realized that there were many more things to that, some of them I have mentioned here.

But I think it will go great and good job :D

@untzag
Copy link
Contributor

untzag commented Jun 19, 2023

(catching up on this comically late)

@beniroquai happi is a tool for building searchable "databases" of hardware interface classes that can be persistent between Python sessions. It's used in a lot of larger Python-based hardware control setups. I really like it for discovery---e.g. ImSwitch could ask happi "what hardware is avaliable" and just go from there. Any third-party or external package can "plugin" via simply describing itself to happi. The best thing? It's actually maintained, by an active team at Stanford.

Entry points are the "built in pluggin system" for Python. Using entry points you can say "my package has this specific relationship to your package", and things will just work. It's very powerful and generic, but isn't focused on hardware interfaces like happi is.

Love what y'all are saying about community building, I feel the same way ❤️

@jacopoabramo
Copy link
Collaborator

@untzag will the source code for happi be published at some point? Or is there I like to check it out?

@untzag
Copy link
Contributor

untzag commented Jun 21, 2023

@jacopoabramo
Copy link
Collaborator

@jacopoabramo https://github.com/pcdshub/happi

I have no idea why I couldn't find the repository. Silly me. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants