# Architecture overview SegSpy is a **microscope-generic, backend-pluggable** segmentation library for HyperSpy. It converts a `Signal2D` into a list of particle objects, then measures generic (particle-type-agnostic) morphology on each. The diagram below shows the end-to-end flow. ```{mermaid} flowchart LR IMG["HyperSpy Signal2D
.dm4 / .tif / ndarray"] subgraph REG["Backend registry (pluggable)"] direction TB TC["traditional_cv
CLAHE → black-hat → threshold → morphology"] SAM["sam (optional)
SAM Auto-Mask + 5-stage filter"] end CFG["SegConfig
from_signal → TEM/SEM"] --> REG IMG --> REG REG -->|segment| MASK["binary mask"] MASK --> EXTRACT["extract_objects
(connected components)"] IMG --> EXTRACT EXTRACT --> OBJ["ParticleObject × N
ROI + mask + calibration"] OBJ --> MORPH["measure_morphology
area · Feret · perimeter · aspect · …"] MORPH --> OUT["per-particle metrics
CSV + labelled PNG"] ``` Three ideas drive the design: 1. **Segmentation is swappable.** Every backend implements the same {class}`~SegSpy.backends.base.SegmentationBackend` interface and is reached through the {class}`~SegSpy.backends.registry.SegmentationRegistry`. `traditional_cv` ships with the core install; `sam` is an optional extra. A new algorithm is just a new registry entry — nothing else changes. 2. **Extract once, measure often.** `extract_objects` produces {class}`~SegSpy.core.ParticleObject` instances carrying the image ROI, mask ROI, and offset. `measure_morphology` runs on those objects, so you can re-measure or change metrics without re-segmenting. 3. **Calibration flows through.** When the input is a HyperSpy `Signal2D`, each object's ROI is itself a calibrated signal, and `get_scale_nm` reads the axis units so length metrics come out in nanometres. > A deeper design-philosophy write-up, per-layer diagrams, and a "write your own > backend" guide are planned for a future release.