Electron-microscopy image analysis — Python/FastAPI port of fermi-viewer
Project description
fermiviewer
Electron-microscopy image analysis: TEM/STEM image viewing, EELS / EDS / diffraction analysis, measurements, and image processing. Python (FastAPI) backend + React frontend + Tauri desktop shell.
Ground-up port of fermi-viewer (MATLAB), and the long-term home of this project line.
Formats: DM3/DM4 (Gatan), EMD (Velox/NCEM), BCF (Bruker), SER (TIA), MRC, HDF5 family (.hspy, NeXus .nxs/.nx5, generic .h5/.hdf5), MSA/EMSA spectra, TIFF, PNG/JPEG/BMP/GIF, headerless RAW, Bruker Nanoscope AFM (.spm/.000). Analysis: EELS (background, maps, quantification ± σ, thickness, Kramers–Kronig, Fourier-log, model-based peak fitting, SVD), EDS (Cliff–Lorimer / ZAF / ζ-factor composition with mass-thickness ± σ, maps, artifacts, peak fitting, composite overlays), diffraction (camera-length & ellipse calibration, CIF phase import, spot detection, phase indexing, d-spacings), GPA strain, CTF estimation, atom columns, particles, grains (k-means / watershed / paint-to-train classifier), cross-section layer & interface-roughness analysis, FFT filtering, drift alignment, Python scripting API, and a full measurement/annotation suite.
Install
Option 1 — Windows installer (recommended)
Grab FermiViewer_x64-setup.exe from the
latest release and run it. It is fully
self-contained (~47 MB) — no Python, no Node, nothing else required.
Launch FermiViewer from the Start menu; closing the window shuts
everything down.
The installer is currently unsigned, so Windows SmartScreen may warn on first run — choose More info → Run anyway.
Option 2 — standalone server (no installer)
Download fv-server-win64.zip from the same release, unzip anywhere, and
run:
fv-server\fv-server.exe
This starts the full app at http://127.0.0.1:8000 and opens your
browser. The server exits on its own when the last tab closes
(--no-auto-shutdown to keep it running, --no-browser to skip the
auto-open).
Option 3 — from source
Requirements: uv (a suitable Python is
fetched automatically) and Node 20+ for the frontend. Get the code with
git clone, or download Source code (zip) from any
release and extract it — no git needed.
git clone https://github.com/pquarterman17/fermiviewer
cd fermiviewer
cd frontend && npm ci && npm run build && cd .. # build the web UI (once)
uv sync # install backend deps
uv run fv # → http://127.0.0.1:8000
That is the whole build — after the first time, uv run fv is all you
run. uv run fv --desktop opens a native window instead of the browser
(pywebview). Building from source needs internet (PyPI + npm) — for a
machine without it, use the ready-made offline bundle in Option 5,
which skips Node and PyPI entirely. For the Tauri shell / installer
build, see Packaging below.
OneDrive checkouts (Windows): if the repo lives in a synced folder, move the venv out of OneDrive's reach before the first sync:
New-Item -ItemType Junction -Path .venv -Target "$env:LOCALAPPDATA\fermiviewer-venv"(
[tool.uv] link-mode = "copy"is already set inpyproject.toml; the junction prevents sync-lock races during installs.)
Option 4 — install from PyPI (pip / uv)
FermiViewer is on PyPI with the web UI already baked into the wheel — no Node, no checkout, no release download; any 64-bit Python 3.10+ works. Install once, then launch from any terminal — including from a folder of images:
uv tool install fermiviewer # exposes `fermiviewer` on PATH
fermiviewer # launch from anywhere
fermiviewer C:\data\session-42 # …or point it at a folder
pip install fermiviewer works too (same wheel; use pip if you don't
have uv). From a source checkout, the equivalent is
uv tool install --from . fermiviewer.
fermiviewer opens a browser tab once the server is confirmed up (no
more racing a cold start), and the in-app Open dialog defaults to the
folder you launched from. If a copy is already running it just opens a
new tab; if port 8000 is taken by another app it steps to the next free
port. fv remains as a short alias for the same entry point.
Option 5 — air-gapped / offline machine (source install, no exe)
For machines with no internet access — or where IT policy rules out
running downloaded executables — each release ships per-OS
fv-offline-*.zip bundles: the FermiViewer wheel (web UI already baked
in) plus every dependency as pre-built wheels and a standard-library-only
installer. The only requirement on the target is a 64-bit Python 3.10+.
- Download
fv-offline-win64.zip(or-macos-arm64/-linux-x64) from the latest release and carry it over. - Extract anywhere writable and run
py install.py(macOS/Linux:python3 install.py). - Launch with the generated
FermiViewer.bat/./fermiviewer.
Everything lives in that one folder (nothing downloaded, no admin
rights); deleting the folder uninstalls it. Full details, including how
to review the exact pinned dependency versions, are in the bundle's
README-OFFLINE.md. To build a bundle yourself from a checkout (on a
connected machine of the same OS):
uv run python tools/offline/make_bundle.py
Usage
| Command | What it does |
|---|---|
fermiviewer / fv |
API + SPA on :8000, opens the browser once healthy, exits when the last tab closes |
fermiviewer <dir> |
…and defaults the in-app Open dialog to <dir> |
fermiviewer --desktop |
Native window (pywebview), exits on close |
fermiviewer --dev |
Vite HMR (:5173) + auto-reloading backend, one terminal |
fermiviewer --no-browser --no-auto-shutdown |
Plain server, stays up |
Open files via File → Open… (the launch-folder list when started from one, otherwise the native picker), drag-and-drop, or File → Open by Path… for large files already on the server's disk. Press ? in the app for the full keyboard map, ⌘K for the command palette.
Documentation
Feature walkthroughs, screenshots, and how-tos live in the project wiki:
- Getting Started — install and your first image
- Viewing & Display — colormaps, the calibrated color scale, scale bar
- Measurements — line/box profiles, distances, ROIs, annotations
- Analysis Workshops — EELS, EDS, diffraction
- Structure & Grains — grain segmentation (incl. paint-to-train), cross-section layer & interface-roughness analysis
- AFM Support — Bruker Nanoscope height maps + Z-scale color bar
- Supported Formats
| Cross-section layer stack | Trained grain classifier |
|---|---|
| Calibrated color scale (AFM height) | EELS analysis |
|---|---|
Development
uv sync --group dev # + ruff, mypy, pytest
uv run pytest # golden-verified; realdata tests
# auto-skip if the corpus is absent
uv run pytest -m "eels and golden" # marker-scoped
uv run ruff check src tests
uv run mypy src
cd frontend
npm run dev # Vite on :5173, /api proxied
npx tsc --noEmit && npm run build
Hard rules (enforced by tests/test_repo_integrity.py):
io/andcalc/are pure libraries — they never import FastAPI/Pydantic;routes/are thin adapters.- 500-line ceiling per source module.
- No GPL runtime dependencies (rosettasciio lives only in the
oracletest group; PyInstaller only in thebundlebuild group). - Physics constants port verbatim from the MATLAB reference — annotated do-not-"fix" items are calibrated/intentional.
Packaging
A tagged push builds and publishes everything automatically
(.github/workflows/release.yml):
git tag v0.2.0 && git push origin v0.2.0
# → Release with the per-OS installers (.exe / .dmg / .deb), the
# fv-server-* standalone archives, the fv-offline-* air-gapped
# bundles, and the auto-updater's latest.json
# → PyPI wheel (SPA baked in), published via trusted publishing after
# a clean-venv install + boot smoke test
Local equivalents (Windows; needs Rust + VS Build Tools for the shell):
cd frontend && npm run build && cd ..
uv sync --group bundle
uv run pyinstaller tools/bundle/fv-server.spec --noconfirm --distpath dist-sidecar
cd src-tauri
npx @tauri-apps/cli@^2 build --config \
'{"bundle":{"resources":{"../dist-sidecar/fv-server":"fv-server"}}}'
The desktop shell shows a loading splash and only navigates to the app once
/api/healthanswers, so a slow first start no longer lands on a "can't reach this page" error. This lives in the Rust shell — installed copies must be rebuilt and reinstalled to pick it up (rebuild the SPA first sofrontend/dist/loading.htmlis bundled).
Project docs
| Doc | Purpose |
|---|---|
docs/parity_report.md |
Three-way parity vs the MATLAB reference + design prototype |
docs/w3_imaging_audit.md |
Per-algorithm port decisions (map / port / hybrid) |
tests/golden/ |
Frozen MATLAB reference values (see tools/matlab/) |
plans/ (local-only) |
Per-machine working plans (gitignored, fermi-viewer convention) |
License
Apache-2.0. Bundled JetBrains Mono is under the SIL OFL
(frontend/public/fonts/OFL.txt).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fermiviewer-0.1.13-py3-none-any.whl.
File metadata
- Download URL: fermiviewer-0.1.13-py3-none-any.whl
- Upload date:
- Size: 849.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e3c98c65f04b2eedb347eb70b8bf1ecba67b44547000af3cb51cc53a52d63da
|
|
| MD5 |
a82975222f6d11d97ec8261ff452362f
|
|
| BLAKE2b-256 |
59f54c0b5f5895d963879e6fd7e0e1188e1696c941da6f13c60cab1a2d98f5bb
|
Provenance
The following attestation bundles were made for fermiviewer-0.1.13-py3-none-any.whl:
Publisher:
release.yml on pquarterman17/fermiviewer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fermiviewer-0.1.13-py3-none-any.whl -
Subject digest:
1e3c98c65f04b2eedb347eb70b8bf1ecba67b44547000af3cb51cc53a52d63da - Sigstore transparency entry: 2111654920
- Sigstore integration time:
-
Permalink:
pquarterman17/fermiviewer@e2f4d3af762f5b7f6d0a799ad82f1a6283ddda65 -
Branch / Tag:
refs/tags/v0.1.13 - Owner: https://github.com/pquarterman17
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e2f4d3af762f5b7f6d0a799ad82f1a6283ddda65 -
Trigger Event:
push
-
Statement type: