Library architecture — overview#
This section is the living class-diagram documentation of the PhysioEx
library (Diagram A). It is extracted directly from the source and is kept in
sync with the code: every class, its public methods and its relationships
mirror physioex/. Each subpackage has its own page:
Data — datasets, preprocessing pipeline, cache, readers, events.
Models — foundation encoders, classic architectures, embeddings, pretrained loading.
Train — training/evaluation loop, metrics, stats, logging, CLIs.
Explain — post-hoc attribution, foundational (CSD), prototypes.
Subsystem map#
flowchart LR
subgraph data["physioex.data"]
REG["datasets.REGISTRY\nget_dataset()"]
BPD["BasePhysioDataset (ABC)"]
PIPE["PreprocessingPipeline\n+ steps"]
CACHE["ChannelCache"]
RD["readers (EDF / annotations)"]
end
subgraph models["physioex.models"]
FE["FoundationEncoder (ABC)"]
ARCH["classic architectures\n(SeqSleepNet, TinySleepNet, ...)"]
EMB["embed / pretrained"]
end
subgraph train["physioex.train"]
TR["Trainer\n(+ multidevice)"]
MET["metrics / stats"]
LOG["Logger (ABC)"]
CLI["bin: train / finetune / test_model"]
end
subgraph explain["physioex.explain"]
PH["posthoc (gradients / DFT / STFT)"]
FO["foundational (CSD)"]
PR["prototypes (NMF / VQ)"]
end
RD --> BPD
PIPE --> BPD
CACHE --> BPD
REG --> BPD
BPD --> TR
FE --> BPD
ARCH --> TR
FE --> TR
TR --> MET
TR --> LOG
CLI --> TR
TR --> EMB
ARCH --> PH
FE --> FO
EMB --> PR
Principal types and cross-cutting relationships#
classDiagram
class BasePhysioDataset {
<<abstract>>
+split(fold)
+__getitem__(idx)
#_list_subjects()*
#_read_subject_labels(spec)*
}
class MultiDataset
class PreprocessingPipeline
class ChannelCache
class FoundationEncoder {
<<abstract>>
+encode(x)
+get_dataset(name)
}
class Trainer {
+train(model, dataset)$
+evaluate(model, dataset)$
+voting_evaluate(model, dataset)$
}
class Logger {
<<abstract>>
}
BasePhysioDataset "1" *-- "1" PreprocessingPipeline : preprocess
BasePhysioDataset "1" *-- "1" ChannelCache : memmap cache
MultiDataset o-- BasePhysioDataset : wraps N
FoundationEncoder ..> BasePhysioDataset : get_dataset()
Trainer ..> BasePhysioDataset : consumes .split()
Trainer ..> Logger : logs to
Design patterns used#
Abstract base classes:
BasePhysioDataset,PreprocessingStep,FoundationEncoder,Logger,SpecificityStrategydefine the extension points.String registry:
physioex/data/datasets/__init__.pymaps names → dataset classes (get_dataset,available_datasets);foundation_checkpoints/foundation_datasetsdo the same for models.Dynamic factory
"module.path:ClassName": resolved byphysioex/train/bin/_common.py:import_classandphysioex/train/models/load.py.Strategy:
SpecificityStrategysubclasses inexplain/foundational/specificity.py; theCHANNEL_STRATEGYclass attribute on encoders.Template method / adapter:
FoundationEncoderwraps heterogeneous pretrained backbones behind a uniform(B,L,C,T) -> (B,L,D)encode.Content-addressed caching:
PreprocessingPipeline.hash()keys the on-diskChannelCache.
Main flows#
Data → tensor:
get_dataset(name)(channels, pipelines, sequence_length)→_list_subjects+ header probe + channel resolution →__getitem__reads channels, applies the compiledPreprocessingPipeline(cached inChannelCache), returns a dict{signals, labels, channel_order, subject, events, ...}collated bydict_collate_fn.Training:
Trainer.train(model, dataset)→build_dataloaders(usesdataset.split(fold)) → hand-written epoch loop →evaluate/voting_evaluate→ metrics/stats, logged via aLoggerbackend. The three CLIs (train/finetune/test_model) share this path throughbin/_common.py.Foundation embeddings:
FoundationEncoder.get_dataset(name)builds the matching preprocessing →encode→extract_embeddings/linear_probe.Explainability: post-hoc gradient/DFT/STFT attributions over a trained classifier;
ConceptualSpectralDecompositionover foundation embeddings; prototype discovery (NMF/VQ) over cached embeddings.