Skip to content

Commit 36fb64c

Browse files
authored
AmSC Genesis (#127)
- New AmSC IRI client with facility, status, account, and compute APIs - Facility adapters for ALCF, NERSC, and OLCF; choose compute resource by name; facility shown in Genesis status table
- New AmSC transfer client - Live status monitoring and shared task-progress reporting for processing and fluorescence pipelines - New token-management CLIs: `ptychodus-iri-tokens` and `ptychodus-transfer-tokens` - Per-facility helper scripts under `src/ptychodus/scripts/genesis/{alcf,nersc,olcf}/` - Update to pty-chi 1.4.0; add Bilinear Hessian reconstructor backend and expose new probe-support methods and magnitude/phase optimization components - Update PtychoPINN-Torch integration: in-memory prediction, multiple-probe-mode export, sync to upstream API - Per-reconstructor model autosave / autoload, wired through the Genesis workflow - Support APS 31-ID LYNX area-detector file format - `ptychodus-bdp`: load bad-pixel masks from file - Clean up diffraction-pattern / probe-position association so pairing is driven strictly by diffraction pattern index, with duplicate-index averaging and interpolation for missing positions; out-of-range patterns are dropped rather than extrapolated - Paganin object builder (single-material phase retrieval from the central diffraction pattern) - Hermite probe builder - Estimate diffraction-pattern crop center and probe-size metrics from raw data - New `ReconstructionAmbiguities` estimator (global complex scale, linear phase ramp, sub-pixel shift) so quality metrics compare reconstructions on equal footing - FRC (Fourier ring correlation) preprocessing, metrics, and GUI panel - Visualize reconstruction residuals (per-pattern modeled-vs-measured diffraction) - Revise affine-transform estimator for probe-position correction (RANSAC, Hodges–Lehmann centering) - Propagator view: improved layout and on-the-fly probe-size metrics - XMCD dialog fixes - Allow and gracefully render NaN values in visualizations - Group navigation subviews in the left-panel toolbar - Diffraction loading progress monitor - Fluorescence enhancer progress monitor (shared `TaskMonitor`) with `enhance_fluorescence_local` workflow API - Auto-size item-view columns - Split the single `Dockerfile` into per-accelerator variants: `Dockerfile.cpu`, `Dockerfile.cuda`, `Dockerfile.rocm`, `Dockerfile.xpu`, each with build-arg knobs (CUDA / ROCm / PyTorch versions, XPU base tag) - Add a `podman` wrapper script (`src/ptychodus/scripts/podman/ptychodus`) that builds, runs, and mounts the container with the right GPU / display / volume flags - New `ptychodus-system-check` CLI for smoke-checking the installed environment - Improved documentation and test coverage
1 parent ced0fe3 commit 36fb64c

217 files changed

Lines changed: 18082 additions & 3908 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "ptychodus (CPU)",
3+
"build": {
4+
"context": "..",
5+
"dockerfile": "../Dockerfile.cpu"
6+
},
7+
"postCreateCommand": "pip install -e .",
8+
"customizations": {
9+
"vscode": {
10+
"extensions": [
11+
"ms-python.python",
12+
"charliermarsh.ruff"
13+
]
14+
}
15+
}
16+
}

.dockerignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.git
2+
.github
3+
dist/
4+
build/
5+
docs/build/
6+
memoized_data/
7+
*.h5
8+
*.npy
9+
*.ini
10+
NOTES
11+
TODO
12+
__pycache__/
13+
*.pyc
Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,89 @@
1-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
1+
# Install ptychodus, run the unit tests, and check lint/types across the
2+
# supported Python versions. See pyproject.toml for the source-of-truth on
3+
# Python version support and tool configuration.
34

4-
name: Python package
5+
name: CI
56

67
on:
78
push:
8-
branches: [ "master" ]
9+
branches: [ "main" ]
910
pull_request:
10-
branches: [ "master" ]
11+
branches: [ "main" ]
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: ${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
1119

1220
jobs:
13-
build:
21+
smoke:
22+
name: Install & CLI smoke (py${{ matrix.python-version }})
23+
runs-on: ubuntu-latest
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
python-version: ["3.11", "3.12", "3.13"]
28+
steps:
29+
- uses: actions/checkout@v4
30+
- name: Set up Python ${{ matrix.python-version }}
31+
uses: actions/setup-python@v5
32+
with:
33+
python-version: ${{ matrix.python-version }}
34+
cache: pip
35+
- name: Install ptychodus (minimal)
36+
run: pip install .
37+
- name: ptychodus --version
38+
run: ptychodus --version
1439

40+
test:
41+
name: Unit tests (py${{ matrix.python-version }})
1542
runs-on: ubuntu-latest
1643
strategy:
1744
fail-fast: false
1845
matrix:
19-
python-version: ["3.10", "3.11", "3.12"]
46+
python-version: ["3.11", "3.12", "3.13"]
47+
steps:
48+
- uses: actions/checkout@v4
49+
- name: Set up Python ${{ matrix.python-version }}
50+
uses: actions/setup-python@v5
51+
with:
52+
python-version: ${{ matrix.python-version }}
53+
cache: pip
54+
- name: Install ptychodus + pytest
55+
run: pip install . pytest
56+
- name: Run pytest
57+
run: pytest tests/ -v
58+
59+
lint:
60+
name: Ruff (lint + format)
61+
runs-on: ubuntu-latest
62+
steps:
63+
- uses: actions/checkout@v4
64+
- name: Set up Python 3.11
65+
uses: actions/setup-python@v5
66+
with:
67+
python-version: "3.11"
68+
cache: pip
69+
- name: Install ruff
70+
run: pip install ruff
71+
- name: ruff check
72+
run: ruff check .
73+
- name: ruff format --check
74+
run: ruff format --check .
2075

76+
typecheck:
77+
name: Mypy
78+
runs-on: ubuntu-latest
2179
steps:
22-
- uses: actions/checkout@v4
23-
- name: Set up Python ${{ matrix.python-version }}
24-
uses: actions/setup-python@v5
25-
with:
26-
python-version: ${{ matrix.python-version }}
27-
- name: Install with minimal dependencies
28-
run: |
29-
python -m pip install --upgrade pip
30-
python -m pip install .
31-
- name: Test CLI with headless minimal install
32-
run: |
33-
ptychodus --version
80+
- uses: actions/checkout@v4
81+
- name: Set up Python 3.11
82+
uses: actions/setup-python@v5
83+
with:
84+
python-version: "3.11"
85+
cache: pip
86+
- name: Install ptychodus + mypy
87+
run: pip install . mypy pyqt5-stubs types-psutil types-pyyaml types-requests
88+
- name: mypy
89+
run: mypy src/ptychodus

.readthedocs.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ sphinx:
1414
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
1515
python:
1616
install:
17-
- requirements: docs/requirements.txt
1817
- method: pip
1918
path: .
19+
extra_requirements:
20+
- docs

CLAUDE.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project
6+
7+
Ptychodus is a ptychography data-analysis application that ingests instrument data, prepares it for processing, and dispatches it through several reconstruction libraries (PtyChi, PtychoPINN, PtychoPINN-Torch). It runs interactively as a PyQt5 GUI, headless via batch CLI, and as a streaming processor inside beamline pipelines (pvapy area-detector). Python ≥3.11.
8+
9+
## Common Commands
10+
11+
Project uses `uv` (preferred) and a developer install with extras.
12+
13+
```sh
14+
# Dev install (preferred). Other available extras: docs, ptychopinn
15+
uv sync --extra globus --extra gui --extra ptychi
16+
17+
# Launch GUI
18+
uv run ptychodus
19+
20+
# Headless batch
21+
uv run ptychodus -b reconstruct -i <input_dir> -o <output_dir>
22+
uv run ptychodus -b train -i <input_dir> -o <output_dir>
23+
# Batch mode reads <input_dir>/settings.ini, <input_dir>/diffraction.h5, <input_dir>/product-in.h5
24+
# (see StandardFileLayout in src/ptychodus/api/io.py)
25+
26+
# Beamline data-prep CLI
27+
uv run ptychodus-bdp --product-name <name> --diffraction-input <h5> \
28+
--probe-position-input <csv> --output-directory <dir> \
29+
--settings <ini>
30+
31+
# Other entry points (see [project.scripts] in pyproject.toml)
32+
uv run convert-to-ptychodus
33+
uv run ptychodus-system-check
34+
uv run ptychodus-iri-tokens # Genesis/IRI auth
35+
uv run ptychodus-transfer-tokens # AmSC data-transfer auth
36+
uv run ptychodus-ptychopinn-tf-test # PtychoPINN TensorFlow smoke check
37+
```
38+
39+
Tests, lint, types:
40+
41+
```sh
42+
uv run pytest # full suite (tests/)
43+
uv run pytest tests/test_io.py # one file
44+
uv run pytest tests/test_io.py::test_name # one test
45+
uv run ruff check . # lint (rules: F, N, NPY)
46+
uv run ruff format . # format (single quotes, line-length 100)
47+
uv run mypy src/ptychodus # type check (py 3.11)
48+
```
49+
50+
CI (`.github/workflows/python-package.yml`) runs four jobs on push/PR to `main`: a `pip install` + `ptychodus --version` smoke test (Py 3.11/3.12/3.13), `pytest tests/`, `ruff check` + `ruff format --check`, and `mypy src/ptychodus`. Run the local equivalents before pushing — CI will block the PR otherwise.
51+
52+
Container & docs:
53+
54+
```sh
55+
podman build -f Dockerfile.cuda -t ptychodus:cuda13.0 . # also: Dockerfile.cpu / .rocm / .xpu
56+
docker build -f Dockerfile.cuda -t ptychodus:cuda13.0 .
57+
make -C docs html # Sphinx docs into docs/build/
58+
```
59+
60+
## High-Level Architecture
61+
62+
### Three-layer separation: api / model / view+controller
63+
64+
- **`src/ptychodus/api/`** — pure-Python domain layer with **no** GUI or model dependencies. Defines core data structures (`Product`, `ProbeSequence`, `Object`, `ProbePositionSequence`, `DiffractionDataset`, `AssembledDiffractionData`), abstract interfaces (`DiffractionFileReader/Writer`, `ProductFileReader/Writer`, `Reconstructor`, `TrainableReconstructor`, `WorkflowAPI`), and infrastructure (`Observable`/`Observer`, `Parameter`/`ParameterGroup`, `SettingsRegistry`, `PluginRegistry`/`PluginChooser`). All other layers depend on this; this layer depends on nothing else in ptychodus.
65+
- **`src/ptychodus/model/`** — application logic. Each subpackage (`diffraction/`, `product/`, `processing/`, `reconstructor/`, `analysis/`, `fluorescence/`, `globus/`, `genesis/`, `automation/`, `agent/`, `visualization/`, `ptychi/`, `ptychopinn/`, `ptychopinn_torch/`) exposes a `*Core` class that owns its settings, repositories, and APIs. `model/core.py::ModelCore` is the composition root: it constructs every `*Core` in dependency order and wires them together. Used both by the GUI and by `__main__.py` batch mode.
66+
- **`src/ptychodus/view/`** (PyQt5 widgets, no logic) and **`src/ptychodus/controller/`** (mediates between widgets and model). Mirror the model package layout. `view/core.py::ViewCore` and `controller/core.py::ControllerCore` are the composition roots; the navigation toolbar order in `ViewCore` is the source of truth for the left/right stacked-panel indexes.
67+
68+
The GUI is optional: `__main__.py` falls back to headless mode if PyQt5 is missing. `ptychodus_stream_processor.py` (the `PtychodusAdImageProcessor`) is the third entry mode and is only imported when `pvapy` is available.
69+
70+
### Index-based pattern/position association
71+
72+
Diffraction patterns and probe positions are paired by **integer scan index**, never by array order. This is what makes streaming and mismatched-rate ingest robust: patterns and positions can arrive from different files or different PV channels, with dropped or extra samples on either side, and the matcher still pairs them correctly.
73+
74+
- Producers: `DiffractionArray.get_indexes()` on the pattern side (`api/diffraction.py`); `ProbePosition.index` on the position side (`api/probe_positions.py`).
75+
- Matcher: `AssembledDiffractionData.prepare_reconstruct_input` in `api/reconstructor.py` treats pattern indexes as authoritative — duplicate position indexes are averaged into anchors, pattern indexes inside the anchor range with no exact position are linearly interpolated, and pattern indexes outside the anchor range are dropped (no extrapolation). The `Product` is rebuilt from the resulting per-pattern positions.
76+
- Round-trip: HDF5 and NPZ product writers persist position indexes via `ProductFileKeys.PROBE_POSITION_INDEXES`.
77+
78+
### Plugin system
79+
80+
File-format support is dynamic. `api/plugins.py::PluginRegistry.load_plugins()` walks `ptychodus.plugins.*` with `pkgutil.iter_modules` and calls each module's `register_plugins(registry)` function. Module-load failures are logged and skipped — this is how optional-dependency plugins (e.g., LCLS, NSLS-II) silently disable themselves.
81+
82+
To add a new file format: create a module under `src/ptychodus/plugins/`, implement the relevant `*FileReader`/`*FileWriter` from `ptychodus.api`, and define `register_plugins(registry)` calling the appropriate `registry.<category>.register_plugin(...)`. For product readers, prefer `register_product_file_reader_with_adapters` so the reader is also reachable as a probe/probe-position/object reader.
83+
84+
### Settings & observers
85+
86+
Settings flow through `api/parametric.py::Parameter[T]` and `ParameterGroup`. Each `*Core` calls `settings_registry.create_group(name)` and creates typed parameters on it. `SettingsRegistry` serializes the full tree as INI. Components react to settings changes through the `Observer`/`Observable` pattern in `api/observer.py`; `PluginChooser.synchronize_with_parameter` is the typical bridge for "settings string → currently selected plugin." When adding cross-component reactivity, hook observers rather than poll.
87+
88+
### Reconstructor libraries
89+
90+
Each reconstructor backend (`model/ptychi/`, `model/ptychopinn/`, `model/ptychopinn_torch/`) exposes a `*ReconstructorLibrary` class. They are constructed in `ModelCore` and passed as a list to `ProcessingCore`. Backends that aren't installed should fail cleanly at import inside their own `__init__.py` — keep the surface a stable `*ReconstructorLibrary` regardless. Reconstructors implement `Reconstructor`/`TrainableReconstructor` from `api/reconstructor.py` and yield `ReconstructOutput` per iteration so the GUI can stream progress.
91+
92+
### Standard HDF5 layout
93+
94+
`api/io.py::StandardFileLayout` is the canonical contract for batch mode and remote workflows: `diffraction.h5`, `product-in.h5`, `product-out.h5`, `fluorescence-in.h5`, `fluorescence-out.h5`, `settings.ini`. `load_diffraction_data` / `save_diffraction_data` and `load_product` / `save_product` round-trip these files; their key names live in `DiffractionFileKeys` / `ProductFileKeys` enums — change those carefully, they are an external interface.
95+
96+
### Remote compute
97+
98+
Two providers, both gated by optional dependencies and constructed by `ModelCore` even when disabled:
99+
100+
- `model/globus/` — Globus Compute submission, used by the original APS workflow.
101+
- `model/genesis/` — IRI/AmSC HPC submission with facility adapters in `model/genesis/facility_adapters.py` and per-facility scripts under `src/ptychodus/scripts/genesis/{alcf,nersc,olcf}/`.
102+
103+
`WorkflowAPI` (see `api/workflow.py` and `model/workflow.py::ConcreteWorkflowAPI`) is the unified façade that GUI, batch mode, and remote workflows all drive.
104+
105+
## Conventions
106+
107+
- Ruff is configured for **single-quoted** strings, 100-char lines, py311 target. The selected lint rules (F, N, NPY) flag pyflakes errors, PEP-8 naming, and NumPy-specific issues. NumPy/Qt-style names (e.g., `probe_energy_eV`, `set_value_from_string`) are accepted via `# noqa: N802/N806/N815` — preserve the unit suffixes on physical quantities; reviewers expect them.
108+
- Type hints are mandatory; `pyproject.toml` lists modules whose missing stubs are intentionally ignored. Keep new code typed and avoid widening that ignore list.
109+
- `model/core.py::ModelCore.is_developer_mode_enabled` is `True` whenever the effective log level ≤ DEBUG (`--log-level 10`). Some controllers gate features (Agent panel, probe-position analysis) behind it.
110+
111+
## Repository Notes
112+
113+
- The git CI workflow targets `main`; local development branches such as `amsc` are active — confirm the intended target before opening PRs.
114+
- Sample `.h5`/`.npy` data and the `dist/` build output in the working tree are typically **untracked** local artifacts — do not stage them in commits unless explicitly asked.

Dockerfile

Lines changed: 0 additions & 20 deletions
This file was deleted.

Dockerfile.cpu

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM python:3.13-slim-trixie
2+
3+
WORKDIR /app
4+
COPY . /src
5+
6+
# Pre-install CPU-only torch from the PyTorch CPU index so the later
7+
# pip install of ptychi sees torch as already satisfied and does NOT
8+
# pull a CUDA-flavored torch wheel from PyPI.
9+
RUN apt-get update && \
10+
apt-get install -y --no-install-recommends git libqt5gui5 && \
11+
rm -rf /var/lib/apt/lists/* && \
12+
python3 -m pip install --root-user-action=ignore --no-cache-dir --upgrade pip && \
13+
python3 -m pip install --root-user-action=ignore --no-cache-dir \
14+
--index-url https://download.pytorch.org/whl/cpu \
15+
torch && \
16+
python3 -m pip install --root-user-action=ignore --no-cache-dir \
17+
/src[globus,gui] \
18+
git+https://github.com/AdvancedPhotonSource/pty-chi.git && \
19+
rm -rf /src
20+
21+
CMD ["python3", "-m", "ptychodus"]

Dockerfile.cuda

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
ARG CUDA_VERSION=13.0
2+
ARG PYTORCH_VERSION=2.12.0
3+
ARG CUDNN_VERSION=9
4+
FROM pytorch/pytorch:${PYTORCH_VERSION}-cuda${CUDA_VERSION}-cudnn${CUDNN_VERSION}-devel
5+
6+
WORKDIR /app
7+
COPY . /src
8+
9+
RUN apt-get update && \
10+
apt-get install -y --no-install-recommends git libqt5gui5 && \
11+
rm -rf /var/lib/apt/lists/* && \
12+
python3 -m pip install --root-user-action=ignore --no-cache-dir --upgrade pip && \
13+
python3 -m pip install --root-user-action=ignore --no-cache-dir \
14+
/src[globus,gui] \
15+
git+https://github.com/AdvancedPhotonSource/pty-chi.git && \
16+
rm -rf /src
17+
18+
CMD ["python3", "-m", "ptychodus"]

Dockerfile.rocm

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
ARG ROCM_VERSION=7.2.4
2+
ARG UBUNTU_VERSION=24.04
3+
ARG PYTHON_VERSION=3.12
4+
ARG PYTORCH_VERSION=2.10.0
5+
FROM rocm/pytorch:rocm${ROCM_VERSION}_ubuntu${UBUNTU_VERSION}_py${PYTHON_VERSION}_pytorch_release_${PYTORCH_VERSION}
6+
7+
WORKDIR /app
8+
COPY . /src
9+
10+
# The base image already includes a ROCm-built torch; pip sees the torch
11+
# requirement satisfied and leaves it alone.
12+
RUN apt-get update && \
13+
apt-get install -y --no-install-recommends git libqt5gui5 && \
14+
rm -rf /var/lib/apt/lists/* && \
15+
python3 -m pip install --root-user-action=ignore --no-cache-dir --upgrade pip && \
16+
python3 -m pip install --root-user-action=ignore --no-cache-dir \
17+
/src[globus,gui] \
18+
git+https://github.com/AdvancedPhotonSource/pty-chi.git && \
19+
rm -rf /src
20+
21+
CMD ["python3", "-m", "ptychodus"]

Dockerfile.xpu

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
ARG BASE_TAG=latest
2+
FROM intel/intel-optimized-pytorch:${BASE_TAG}
3+
4+
WORKDIR /app
5+
COPY . /src
6+
7+
# The base image already includes Intel-optimized torch (with IPEX / XPU
8+
# support for ALCF Aurora); pip sees the torch requirement satisfied and
9+
# leaves it alone.
10+
RUN apt-get update && \
11+
apt-get install -y --no-install-recommends git libqt5gui5 && \
12+
rm -rf /var/lib/apt/lists/* && \
13+
python3 -m pip install --root-user-action=ignore --no-cache-dir --upgrade pip && \
14+
python3 -m pip install --root-user-action=ignore --no-cache-dir \
15+
/src[globus,gui] \
16+
git+https://github.com/AdvancedPhotonSource/pty-chi.git && \
17+
rm -rf /src
18+
19+
CMD ["python3", "-m", "ptychodus"]

0 commit comments

Comments
 (0)