README.md of the spam-gui repository, shown as HTML.spam-gui
Graphical modules for spam (Software for the Practical Analysis of Materials), in a napari viewer.
The first module is the multimodal registration (MMR): it registers two 3D images of the same sample acquired with different modalities (e.g., x-rays and neutrons). The registration itself is spam's; spam-gui guides you through it, step by step:
- Load images (at a chosen binning, reusing the eye registration, crop and MMR registration of a coarser one). The two images can have different sizes: image 1 is shown on the voxels of image 2, the reference, centre on centre, and everything is done on image 2's voxels
- Eye registration (pairs of points). It carries the scale too, if the voxel sizes differ (« Zoom »: e.g., 2 for voxels of image 1 twice as large): Phi then takes image 1 about its centre to image 2 about its centre, with that scale
- Crop
- Joint histogram, in three panes: grey level mapping (the grey levels of each image spread over the bins); bin and peak selection (the bins, how the peaks are found, « Compute histogram »); the joint histogram with its peaks to tick (fitted by Gaussians). It is seen from above, or as a 3D surface in an isometric view rotated about its vertical axis with a slider
- Phase diagram
- MMR registration
plus a Summary, available at any time.
Install
spam-gui is not on PyPI yet: it is installed from its GitLab repository, in a virtual environment as spam is. Installing it also installs spam (0.9.1 or later, as released: nothing in spam needs changing), napari and PyQt6 (Qt 6). It needs Python 3.10 or later. The commands below are for Ubuntu or Debian (and WSL).
spam is a dependency of spam-gui: pip installs it, so it is not installed on its own. Only the system libraries that pip cannot install come from apt: those spam needs, those of napari's window (Qt's display libraries), and git. apt installs only those missing: on an Ubuntu desktop, most are already there.
To use it
# install minimal system deps
sudo apt install python3-venv git libglu1-mesa libxcursor1 libxft2 libxinerama1 libgomp1 libgl1 libglib2.0-0 libdbus-1-3 \
libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-cursor0
# Create a virtual environment (or skip this line to install spam-gui in an existing spam-venv)
/usr/bin/python3 -m venv spam-venv
# Activate your virtual environment
source spam-venv/bin/activate
# update python package manager
pip install -U pip
# install spam-gui (and with it spam, napari and PyQt6)
pip install "git+https://gitlab.com/spam-project/spam-gui.git"
Without git, the last line can be pip install https://gitlab.com/spam-project/spam-gui/-/archive/main/spam-gui-main.zip.
To update it later (its version number does not change yet, so a plain upgrade may skip it), in the activated environment:
pip install --force-reinstall --no-deps "git+https://gitlab.com/spam-project/spam-gui.git"
spam-gui used Qt 5 (PyQt5) before it moved to Qt 6: an environment installed then still has PyQt5, which napari would pick, and fail (« napari requires Qt >= 6.7.0, but PyQt5 … was imported »). Once, before the update above, replace it (and install libxcb-cursor0 with apt):
pip uninstall -y PyQt5 PyQt5-Qt5 PyQt5-sip
pip install -U "napari[pyqt6]"
To develop it (e.g., to write a new module)
The code is cloned, and installed in editable mode (it follows the code as it is edited), with the test modules:
# install minimal system deps, and xvfb (a virtual screen: the window test and screenshots at any screen size, unseen)
sudo apt install python3-venv git libglu1-mesa libxcursor1 libxft2 libxinerama1 libgomp1 libgl1 libglib2.0-0 libdbus-1-3 \
libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-cursor0 \
xvfb
# Create a virtual environment (next to the code, not in it)
/usr/bin/python3 -m venv spam-venv
# Activate your virtual environment
source spam-venv/bin/activate
# update python package manager
pip install -U pip
# get the code (or git@gitlab.com:spam-project/spam-gui.git, with write access)
git clone https://gitlab.com/spam-project/spam-gui.git
cd spam-gui
# install spam-gui in editable mode, with the test modules (pytest, pyflakes)
pip install -e ".[dev]"
To update it: git pull. Before writing a module, read SPEC.md (see « Writing a new module » below).
Start
spam-gui # asks which module to open
spam-gui mmr [image1 image2]
spam-gui --help # the modules; spam-gui MODULE --help: the arguments of a module
Each module is a subcommand, with its own arguments. mmr, the multimodal registration: the images (TIFF files, or folders of TIFF slices) are optional; image 1 is moved onto image 2, the reference. From an open napari window: Plugins › spam › spam-gui.
On Linux, spam-gui uses X11 (QT_QPA_PLATFORM=xcb), also in a Wayland session: under Wayland a program cannot place its windows (its pop-ups would not open at the centre of the window), and napari's drawing can fail (it does under WSL). It also sets PYOPENGL_PLATFORM=glx (unless already set), so that napari's drawing finds the OpenGL context Qt made with X11. Started from napari's menu instead, it uses the display napari chose.
The window
The window opens within its screen (maximised the first time, or if the size it had does not fit the screen). Its panels follow its size:
- the images are shown in one, two or three windows side by side (« Single », « Double », « Triple », on the right): at first, both images in one window; image 1 on the left and image 2 on the right; image 1, image 2 and both in a checkerboard. Each view keeps its windows' settings;
- the borders between the panels, and between the image windows, can be dragged (a double click on a border between two windows gives them the same width again);
- the two small buttons at the far left and right, just above the panels, hide and show the panels on that side, to give the images more room;
- napari's menus (File, View, Layers...) are hidden: Ctrl+M shows them (and hides them again);
- the panels are always there (they cannot be closed or moved); the layer controls and the layer list can be collapsed to one line by a click on their title (▾, ▸), to leave more height to the other;
- the layer controls show the basic controls of a layer (an image: its opacity, its histogram and contrast limits, its colormap); « ▸ Advanced » shows the others, the 3D ones among them (labelled « (3D) »);
- in a narrow window, the steps show their numbers only (their titles are in their tooltips), and what does not fit in a panel scrolls.
Large images
Images of several GB each can be larger than the memory: spam-gui does not need them in memory.
- Coarse binnings first. Register at a coarse binning (e.g., 16 or 4), then load a finer one with the eye registration, crop and MMR registration of the coarser one ticked (step 1). The joint histogram and the phase diagram (steps 4, 5) are made again at each binning: their peaks change with the binning.
- At full resolution (binning 1), an image is read from its file as it is used, when the file allows it: a single TIFF file that is not compressed. A compressed file or a folder of slices is loaded in memory if it fits there; otherwise it is first copied into a scratch file of the same size.
- Long calculations (reading and binning, the joint histogram, saving the images) run a part of the image at a time, in threads, with a progress bar and a button to cancel.
- The registration itself (step 6) is spam's, and needs its region in memory: about 60 bytes for each voxel (2 GB for 320³ voxels, 60 GB for 1000³). Step 6 says how much the region needs and how much is available, and asks before starting a registration that does not fit. At full resolution, register a crop (step 3).
- 3D views need both images whole in memory: they are refused for images that do not fit (load a coarser binning for a 3D view).
- Scratch files (an image that cannot be read as it is used, or image 1 moved on a very large crop) go to the temporary folder, and are deleted when they are no longer used. To put them elsewhere (e.g., on a larger or faster disk):
SPAM_GUI_SCRATCH=/path/to/folder spam-gui.
Writing a new module
New modules follow SPEC.md: how a module is built (steps, panes, shared files), how it looks and behaves, and how it is tested. It is written so that it can also be given to Claude: in this repository, ask Claude Code to read SPEC.md, then to build the module.
Tests
From a developer install (see « To develop it » above):
pytest tests
One more test drives the window itself through the whole registration, on a small pair of images it makes. It opens the window for about a minute, so it only runs when asked:
SPAM_GUI_TESTS=1 pytest tests/test_gui.py
To run it on a virtual screen (xvfb, see « To develop it »), unseen, at a chosen screen size:
SPAM_GUI_TESTS=1 xvfb-run -a -s "-screen 0 1920x1080x24" env QT_QPA_PLATFORM=xcb LIBGL_ALWAYS_SOFTWARE=1 pytest tests/test_gui.py
Docs as a website
The Markdown files of the repository (this one, SPEC.md, TODO.md, OPEN_QUESTIONS.md, TO_SPAM.md, the specs) are published as a website by GitLab Pages on each push to the default branch (.gitlab-ci.yml). To build it locally, from a developer install: python scripts/pages.py, then open public/index.html.
Licence
GPL-3.0-or-later, as spam (see LICENSE.md).