Skip to content

Instamatic's modular design #152

@Baharis

Description

@Baharis

Introduction

Instamatic as a whole is designed to be a very modular. Several "areas" of the program easily accept new additions that either expand program capabilities or allow replacing existing ones. We can list many modular areas of Instamatic, including:

  • microscope interfaces: individual files @ microscope/interface/ directory or external (e.g. instamatic_tecnai_server);
  • camera interfaces: sets of files @ camera directory or external (e.g. instamatic_TEM_emulator);
  • controller jobs: one file @ gui/jobs.py (e.g. collect_flatfield.py);
  • experiment routines: individual sub-directories @ experiments/ directory (e.g. cred/);
  • GUI modules: individual files @ gui/ directory (e.g. cred_frame.py);
  • calibration routines: individual files @ calibrate/ directory (e.g. cred_frame.py).

Multiple areas that are not "modular" per-se are designed in a clear way that allows easy introduction of modularity:

  • server directory: stores individual files @ servers/ (that are for some reason mostly independent);
  • image formats: individual files @ formats/ collect tools for diffraction image handling;
  • image processing: individual files @ processing/ handles saving and modifying images;

Litany of issues

The overall structure looks fine at the first glance, but the closer you look, the more cracks you start to see. The microscope and camera interface design is, in my opinion, the best part of the code, largely thanks to @viljarjf's refactoring in #91. However, their internal structure is different, with the camera parts being much less organized. Until recently, the camera server would not even work properly, and the communication protocols used by camera and microscope differ (e.g. func_name vs attr_name). More on that later. Adding new microscopes and cameras is mostly straightforward but require some tricks e.g. the GUI and server config interface must differ.

instamatic.microscope structure instamatic.camera structure Whatever is going on between experiments and GUI
Image Image Image

Small controller jobs are held in gui/jobs.py which is completely fine by itself. However, to register more jobs, they need to be added in particular Instamatic directory with a fixed format, which starts being odd. This becomes even more problematic, when we remember about GUI modules. Most of the GUI modules are there to offer interface to some experiments i.e. job – adding an experiment type is always associated with adding GUI window. If that is the case, then why are they located in two completely different places? Why are experiments accessed via gui modules (they import experiments to define commands themselves)?

Microscopes and cameras can be defined outside Instamatic and developed under a separate license which is great, as it allows their development in private repositories. However: jobs, experimental routines, GUI modules, calibrations, image formaters/processors are fixed in store and MUST be developed as part of Instamatic. The only way to have these hidden from them community is creating a private fork that will rarely or never be updated due to conflict issues. This does raise the barriers for new features to be re-implemented into the main branch; and we know some companies and researches are unwilling to dedicate time to that.

instamatic.microscope.client instamatic.camera.camera_client instamatic.goniotool
Image Image Image

Servers (and calibrations, to some degree) are another can of worms. Despite being structurally very similar, the amount of repetition between individual scripts is massive. Microscope, camera, and goniotool servers use mostly the same architecture but NO inheritance. Improvements and bug-fixes that make their way into one of them further increase the disparity between their mechanisms instead of addressing common issues. The communication mechanism is also simple but finicky: instructions and results are sent using two different protocols and do not allow for asynchronous evaluation. Because they send and receive directly using socket.send and socket.recv they are bare-bones and super-fast, but also super-easy to break. For a nice example, neither of these commands assumes that the message must be passed in a single piece: it just happens to, and so Instamatic communication relies on a series of happy accidents.

Identifying improvement areas

I did not spend 2 hours writing this text just to complain or bash Instamatic – au contraire, I find its design philosophy highly appealing, to the point where I decided to make it a centerpoint of my everyday work. I would rather use this issue as a discussion, where anyone can list loose ideas for development. I intend to update it as needed, starting from the issues I have listed above:

  • TEM/cam interface structure is incomplete and inconsistent, may be generalized for more devices (precession/temp control?);
  • All client-server communication uses inheritance and simplistic protocols (prevent yielding, asynchronicity);
  • Jobs, experiments, and GUI elements are scattered and can't be implemented and imported from outside Instamatic;
  • Calibration routines include no clear inheritance or defined design philosophy, not obvious which are still used/usable;
  • Image processing and output saving is only partially generalized and does not easily allow for extensions;

Given time, I would personally like to focus on the jobs/experiments structure. In my opinion it is the lowest-hanging and best-defined fruit that could be easily addressed using importlib entry points. For example, what bothers me right now is the existence of 3 different classes designed to run the same cRED experiment. None of them has an active maintainer, and from my personal perspective 2 of them contribute nothing but maintenance burden. Having them in a separate repository with dedicated goal and maintainer would allow its use to the groups they were originally designed for while having a known maintainer and keeping the GUI clear for the core functionality.

Motivation and some thoughts

I wrote about all of these issues as a way to conceptualize, collect, and put on paper all the issues or ideas that I've had with/for the code in the last year. I would like to give others an option to do the same, as well as create a little space where we can declare some abstract ideas about the direction we may want to push the development of Instamatic in the future. This is not expected to be a TODO list: in fact, some of the things I suggest here are likely moronic and out-of-touch. But I would love to have a discussion whether that is the case and which ideas reverberate with others, developers, users, or future-myself-that-found-some-time-for-coding the most.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions