Architecture¶
CGMPy follows a facade + modular design: a small public API at the top, a deeper modular structure beneath, each layer independently testable.
Layers¶
┌─────────────────────────────────────────────────────────────┐
│ Public API (cgmpy/__init__.py) │
│ GlucoseAnalysis, GlucoseData │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────┼────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
│ cgmpy.data │ │ cgmpy.metrics│ │ cgmpy.plotting │
│ │ │ │ │ │
│ loader │ │ basic │ │ agp │
│ processor │ │ time_in_range│ │ daily_plots │
│ analyzer │ │ variability │ │ statistical_plots│
│ exporter │ │ pregnancy │ │ │
│ specialized │ │ targets │ │ │
│ core │ │ │ │ │
│ pregnancy │ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────────┘
│ │ │
└──────────────────┼────────────────────┘
▼
┌──────────────────┐
│ cgmpy.analysis │
│ GlucoseAnalysis │
│ (orchestrator) │
└──────────────────┘
│
▼
┌──────────────────┐
│ cgmpy.agata │
│ (cross-check │
│ vs. reference) │
└──────────────────┘
Data flow¶
A typical CGMPy session looks like:
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ CSV │────▶│ Loader │────▶│Processor │────▶│ Analyzer │
│ /DF │ │ │ │ │ │ │
└─────────┘ └──────────┘ └──────────┘ └────┬─────┘
│
┌───────────────────────────────────┘
▼
┌─────────────┐ ┌──────────┐
│ Metrics │────────▶│ Plotter │
│ layer │ │ │
└──────┬──────┘ └──────────┘
│
▼
┌─────────────┐
│ Report │
│ (JSON-like │
│ dict) │
└─────────────┘
Key design decisions¶
CGMPy's main design decisions are recorded as ADRs. The most important ones:
- Pure functions + composition (ADR 0005)
— every metric is a standalone pure function over a
pandas.Series(importable fromcgmpy.metrics), and the high-levelGlucoseAnalysisfacade composes them. This superseded the earlier facade + mixin design (ADR 0003); theModular*/*Metricsmixin classes were removed in v0.6.0. - NumPy / pandas first — every metric is implemented with vectorized
operations over
pandas.Series, not Python loops. - AGATA parity — the
agataoptional dependency is the reference implementation; CGMPy cross-validates against it where the API overlaps. - English only — code, comments, docstrings, documentation, commit messages, and PR descriptions are in English.
Module responsibilities¶
| Module | Responsibility |
|---|---|
cgmpy/data/loader.py |
File I/O and format detection. |
cgmpy/data/processor.py |
Validation, type coercion, dedup. |
cgmpy/data/analyzer.py |
Gap detection, quality scoring, summaries. |
cgmpy/data/exporter.py |
Parquet / CSV / Excel export. |
cgmpy/data/specialized.py |
Vendor-specific loaders. |
cgmpy/data/pregnancy_data.py |
Pregnancy-window trimming. |
cgmpy/data/core.py |
GlucoseData facade (wires the above). |
cgmpy/metrics/basic.py |
Mean, median, GMI, SD, CV, IQR, percentiles. |
cgmpy/metrics/time_in_range.py |
TIR, TAR (½), TBR (½). |
cgmpy/metrics/variability.py |
CV, MAGE, MODD, CONGA, J-Index, LBGI, HBGI, GRI, ADRR. |
cgmpy/metrics/pregnancy.py |
Pregnancy-specific metrics. |
cgmpy/metrics/targets.py |
GlucoseTargets dataclass + helpers. |
cgmpy/plotting/agp.py |
Ambulatory Glucose Profile. |
cgmpy/plotting/daily_plots.py |
Daily trace plots. |
cgmpy/plotting/statistical_plots.py |
Histograms, TIR breakdown. |
cgmpy/analysis/core.py |
GlucoseAnalysis facade (load + metrics + plot). |
cgmpy/agata/metrics.py |
AgataAnalysis wrapper around the AGATA library. |
cgmpy/utils/ |
Helpers (date parsing, range validation, …). |
Public API stability¶
Symbols exported from cgmpy/__init__.py are stable. To change one:
- Add a
DeprecationWarningin the same release. - Document the change in
CHANGELOG.md. - Remove the old symbol after 1 minor version.