Formal temporal and causal structure for consistent clinical data across systems (HL7 v2, FHIR, MLLP). EUPL-1.2 / commercial dual license.
Project description
AION Clinical
Formale Wissensrepräsentation für klinische Verläufe — Referenzimplementierung der mathematischen Strukturen aus AION_v1.0.
Was ist drin
Diese Bibliothek implementiert fünf zentrale Bausteine:
- Typ-Hierarchie
H = (T ∪ {⊤}, ≺)— DAG mit Eager-Validierung, transitive Hülle gecacht, Multi-Inheritance optional. - Ereignismodell
e = (p, a, τ, α, ρ)mit typisierten Referenzenρ : E → R— Beziehungen zwischen Ereignissen sind benannt (confirms,rules_out,caused_by,response_to, …) und bilden einen echten Knowledge-Graph. - Allen-Algebra — alle 13 disjunkten Zeitintervall-Relationen, plus eine unscharfe Variante mit Monte-Carlo-Schätzung.
- Kausaler Graph — gerichteter azyklischer Graph mit do-Operator, Backdoor-Adjustierung nach Pearl, formaler d-Separations-Validierung.
- TCFG — temporale kontextfreie Grammatik in Chomsky-Normalform mit exaktem CYK-Parser, approximativem Beam Search und Pattern-Mining für klinische Phasen-Erkennung.
Hinzu kommt aion.verify — Schema-Konsistenz und kausale Verifikation:
- Multi-Inheritance-Konfliktcheck (disjunkte Ranges, Type-Mismatch, Enum-Specialization)
- Required-Attribute-Berechnung über die transitive Hülle
- d-Separation per Lauritzen-Verfahren
- Backdoor-Set-Validierung mit konkreten Verletzungs-Reports
- Optionales Z3-SMT-Plugin für Schema-Erfüllbarkeitsprüfung
Sowie aion.fhir — Round-Trip-Mapper zum FHIR-Standard:
to_fhir(event)/from_fhir(resource)für Observation, Condition, MedicationAdministration, Procedureto_fhir_bundle(events)/from_fhir_bundle(bundle)für ganze Patient-Timelines- Garantierte Round-Trip-Stabilität (alle AION-spezifischen Felder via Extensions)
- Lädt nur, wenn
fhir.resourcesinstalliert ist (lazy import)
Designprinzip
Stdlib zuerst. Der Kern hat genau eine echte Abhängigkeit (PyYAML zum
Lesen von Schemata). Die GUI baut auf PySide6 (LGPL-lizenziert, also frei
für jede Nutzung — privat wie kommerziell). Alles andere — Causal-Inference-
Frameworks, FHIR, FastAPI — sind optionale Plugins. Du kannst die Bibliothek
auf einer Embedded-Box ohne Internet installieren und sie funktioniert.
Konkret heißt das:
TypeHierarchy: Adjazenzlisten +functools.lru_cache, kein NetworkX.CausalGraph: eigene Topo-Sort/Backdoor-Logik, kein DoWhy nötig.SQLiteEventStore: nursqlite3aus stdlib, keine SQLAlchemy.GUI: PySide6 (Qt 6, LGPL), nicht PyQt6 (GPL) — kein Lizenzthema bei kommerzieller Weitergabe.FuzzyAllenInterval: Monte-Carlo mitrandom.gauss, kein NumPy nötig.
Installation
Endanwender — von PyPI
# Minimaler Kern (nur PyYAML + Python-stdlib)
pip install aion-clinical
# Mit Optional-Features (eckige Klammern: Extras-Syntax)
pip install "aion-clinical[fhir]" # + FHIR-R4 Roundtrip
pip install "aion-clinical[gui]" # + PySide6 GUI
pip install "aion-clinical[causal]" # + DoWhy für kausale Inferenz
pip install "aion-clinical[verify]" # + Z3 SMT-Solver
pip install "aion-clinical[ldap]" # + LDAP/AD-Auth (ldap3)
pip install "aion-clinical[oidc]" # + OIDC-Auth (authlib)
pip install "aion-clinical[all]" # alles
Python 3.10+ erforderlich. Smoke-Test direkt nach Installation:
aion --version # → aion 1.10.3
python -m aion.examples.basic_usage
Entwickler — aus dem Source-Repository
git clone https://codeberg.org/iscad/aion.git aion-clinical
cd aion-clinical
python3 -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
pip install -e ".[dev,verify,fhir,gui]"
python -m pytest tests/ # → 364 passed
PySide6 ist nur nötig, wenn Du die GUI bauen willst — Backend, Tests und Beispiele laufen auch ohne.
Schritt-für-Schritt-Anleitung mit allen Optionen: Das vollständige
BENUTZERHANDBUCH.mdist in der Source-Distribution enthalten (pip download aion-clinical --no-binary :all:) oder im Codeberg-Repo verfügbar.
Schnellstart
from datetime import datetime
from aion import TypeHierarchy, ClinicalEvent, SQLiteEventStore
# 1. Typ-Hierarchie aus YAML laden
h = TypeHierarchy.from_yaml("schemas/clinical_base.yaml")
print(h.is_subtype("Herzinfarkt", "Diagnose")) # True
# 2. Ereignis erzeugen
now = datetime(2026, 1, 1, 12, 0)
e = ClinicalEvent(
patient_id="P001",
event_type="Sepsis",
t_start=now, t_end=now,
stay_start=datetime(2026, 1, 1, 10, 0),
stay_end=datetime(2026, 1, 5),
attributes={"sofa_score": 8, "lactate": 4.2},
)
# 3. Persistieren
with SQLiteEventStore("clinical.db") as store:
store.add(e)
for ev in store.find_by_patient("P001"):
print(ev.event_type, ev.t_start)
GUI starten
aion-gui # In-Memory-DB
aion-gui patients.db # Persistente DB
Die GUI hat fünf Tabs:
- Typ-Hierarchie — Tree-Editor mit Detail-Panel und Validator.
- Ereignisse — Tabelle mit SQLite-Persistenz, Filter nach Patient.
- Allen-Relationen — interaktive Slider, alle 13 Relationen + Fuzzy-Verteilung.
- Kausalgraph — Drag-and-Drop-Editor mit Backdoor-Highlight und Demo-Inferenz.
- Schema-Editor — YAML-Editor mit Live-Validierung.
Kausalgraph-Tab im Detail
Der Causal-Graph-Tab nutzt QGraphicsScene und ist ein interaktiver Editor:
| Aktion | Effekt |
|---|---|
| Doppelklick auf leeren Canvas | Neuen Knoten anlegen |
| Klick + Ziehen auf Knoten | Knoten verschieben (nativ via ItemIsMovable) |
| Shift+Klick auf zwei Knoten | Gerichtete Kante (1.→2.) |
| Rechtsklick auf Knoten/Kante | Kontextmenü mit „Löschen" |
| Treatment/Outcome wählen | Backdoor-Set wird rot markiert, Nachfahren grau |
Die Demo-Inferenz nutzt ein Sigmoid-Modell mit synthetischen Daten,
um P(Y=1 | do(X=1)) per Backdoor-Adjustierung zu berechnen. Für reale
Anwendungen lädst Du Deine eigenen Verteilungen via do_backdoor().
SQLite-Persistenz
Schema in einer Übersicht:
events event_references
───────────────────── ────────────────────
event_id PK event_id ──┐
patient_id ◄── idx ref_id ──┴── PK
event_type ◄── idx
t_start ◄── idx
t_end
stay_start, stay_end
attributes (JSON)
confidence
created_at, updated_at
Indizes sind auf typische klinische Abfragen optimiert:
(patient_id, t_start), event_type, t_start. JSON-Spalte erlaubt
Attribut-Suche via json_extract. Many-to-many-Referenzen (ρ ⊆ E) gehen
über die separate Tabelle mit Foreign-Key-Cascade.
Architektur
src/aion/
├── core/ # stdlib-only Kern
│ ├── types.py # TypeHierarchy
│ ├── events.py # ClinicalEvent (mit typisierten ρ : E → R)
│ ├── relations.py # EventRelation: confirms, response_to, ...
│ ├── temporal.py # Allen + Fuzzy
│ ├── causal.py # CausalGraph + Backdoor
│ ├── tcfg.py # CYK + Beam Search + Pattern-Mining
│ └── builder.py # TypeBuilder, @aion_type
├── persistence/
│ └── sqlite_store.py # SQLiteEventStore (mit relation-Spalte)
├── verify/ # Schema- und kausale Verifikation
│ ├── hierarchy.py # Multi-Inheritance-Konflikte (stdlib)
│ ├── causal.py # d-Separation, Backdoor-Validierung (stdlib)
│ └── z3_plugin.py # SMT-Erfüllbarkeit (optional, lazy)
├── fhir/ # FHIR-Mapper (optional, lazy)
│ ├── mapper.py # to_fhir / from_fhir pro Resource-Typ
│ ├── bundle.py # Bundle ↔ list[ClinicalEvent]
│ └── codes.py # System-URLs (LOINC, SNOMED, ATC, AION)
└── gui/ # PySide6 (Qt for Python, LGPL-3.0)
├── app.py
└── tabs/
├── type_editor.py
├── events_tab.py
├── allen_tab.py
├── causal_tab.py
└── schema_tab.py
schemas/ # Beispiel-YAMLs (clinical_base, icu_extension, cardiology_extension)
tests/ # unittest-basiert (122 Tests grün)
examples/ # Skripte zum Ausprobieren
Verifikation (aion.verify)
Drei stdlib-only Prüfungen plus optionales Z3-Plugin:
from aion import (
TypeHierarchy, CausalGraph,
check_inheritance_conflicts, is_valid_backdoor_set, has_z3,
)
# 1. Multi-Inheritance-Konsistenz
h = TypeHierarchy.from_yaml("schemas/clinical_base.yaml")
report = check_inheritance_conflicts(h)
print(report.summary()) # findet disjunkte Ranges, Type-Mismatch, Enum-Verletzungen
# 2. Formale Backdoor-Validierung via d-Separation (Lauritzen)
g = CausalGraph()
g.add_edge("Z", "X"); g.add_edge("Z", "Y"); g.add_edge("X", "Y")
report = is_valid_backdoor_set(g, "X", "Y", {"Z"})
# → ✅ Z = ['Z'] für X → Y
# 3. SMT-Erfüllbarkeit (nur mit pip install z3-solver)
if has_z3():
from aion.verify.z3_plugin import check_schema_satisfiability
sat = check_schema_satisfiability(h, "Sepsis")
print(sat) # zeigt UNSAT-Beweis oder konkretes Modell
Anders als die heuristische Variante in CausalGraph.find_backdoor_adjustment_set()
ist is_valid_backdoor_set() formal nach Pearl korrekt — es liefert konkrete
Verletzungs-Reports (welcher Pfad nicht blockiert ist, welcher Knoten
unzulässigerweise Nachfahre des Treatments ist).
Tests
python -m pytest tests/ # mit pytest
python -m unittest discover # mit stdlib-unittest
Die Tests laufen ohne externe Abhängigkeiten außer PyYAML. Z3- und FHIR-Tests
werden übersprungen, falls die jeweiligen Optionalpakete fehlen
(skipUnless-Decorator). Mit allen Optionen —
pip install -e ".[dev,verify,fhir]" — sind 154 Tests grün.
FHIR-Mapper (aion.fhir)
Round-Trip zwischen ClinicalEvents und FHIR-Resourcen:
from aion import ClinicalEvent, EventRelation, TypeHierarchy
from aion.fhir import to_fhir_bundle, from_fhir_bundle, bundle_to_file
h = TypeHierarchy.from_yaml("schemas/clinical_base.yaml")
events = [...] # Liste von ClinicalEvents
# Export
bundle = to_fhir_bundle(events, type_hierarchy=h)
bundle_to_file(bundle, "patient.json")
# Reimport (z. B. von HAPI-FHIR-Server oder Synthea)
from aion.fhir import bundle_from_file
bundle = bundle_from_file("synthea_export.json")
events = from_fhir_bundle(bundle) # ignoriert nicht unterstützte Resourcen
Unterstützte Resource-Typen: Observation, Condition,
MedicationAdministration, Procedure. Andere (Patient, Encounter,
DiagnosticReport, …) werden beim Reimport ignoriert, statt das gesamte
Bundle abzulehnen.
AION-spezifische Felder (typisierte Beziehungen, Konfidenz, Aufenthalts-
Periode) werden als FHIR-Extensions mit AION-eigenen System-URLs
gespeichert — siehe aion/fhir/codes.py. Damit ist der Export
FHIR-konform und Round-Trip-stabil.
Beispiele
Die Demos liegen ab 1.10.3 als Sub-Package aion.examples direkt im
installierten Paket — also nach pip install aion-clinical sofort
ausführbar:
python -m aion.examples.basic_usage # Builder, Decorator, YAML
python -m aion.examples.sqlite_demo # Persistenz mit typisierten Refs
python -m aion.examples.causal_inference_demo # Backdoor-Adjustierung
python -m aion.examples.phase_a_demo # Knowledge-Graph + Pattern-Mining + Verify
python -m aion.examples.fhir_demo # FHIR-Bundle Round-Trip
python -m aion.examples.cardiology_demo # STEMI-Verlauf mit kombiniertem Schema
python -m aion.examples.hl7v2_demo # HL7-v2-Datei-Import
python -m aion.examples.mllp_demo # HL7-v2-MLLP-Live-Listener
python -m aion.examples.auth_demo # API-Key-Auth + MLLP
python -m aion.examples.synthea_demo # Synthea-Bundle-Import
Die mitgelieferten Schemas (clinical_base.yaml,
cardiology_extension.yaml, icu_extension.yaml) liegen in
aion.schemas und sind über importlib.resources.files('aion.schemas')
zugreifbar.
Erweiterungen (geplant / optional)
- FHIR-Mapper —
aion.fhir: Round-Trip zwischenClinicalEventundfhir.resources.Observationetc. - DoWhy-Bridge —
aion.causal.dowhy_bridge:CausalGraph→ DoWhy zur Sensitivitätsanalyse. - REST-API —
aion.api: FastAPI-Endpoints für Schema und Events. - Async-Streams — falls echte Echtzeit-Anbindung nötig wird, kann
asyncio.Queueohne Kafka eingesetzt werden.
Migration von 1.0.x
Wenn Du AION 1.0.x kennst und auf 1.10.x umsteigst: die Mathematik-API
(Interval, classify()) wurde umbenannt in AllenInterval und
relation_to(), das Storage-Modell ist jetzt ClinicalEvent plus
SQLiteEventStore, und HL7/FHIR/MLLP/Auth sind als Plugins dazugekommen.
Eine vollständige Mapping-Tabelle und Code-Beispiele liegen in
MIGRATION.md (in der Source-Distribution oder im
Codeberg-Repo).
Lizenz
AION Clinical wird unter Dual-Lizenz angeboten:
-
EUPL-1.2 (Open Source) — European Union Public Licence v1.2. Volltext in
LICENSE(deutsche Kurzfassung) undLICENSES/EUPL-1.2.txt(englische SPDX-Standardfassung). -
Kommerzielle Lizenz — für proprietäre Verwendung, abweichende Bedingungen oder Support-Verträge.
Copyright © 2026 Friedhelm Matten / ISCaD GmbH, 30900 Wedemark, Germany. Kontakt für kommerzielle Lizenz: licensing@iscad-it.de
Source-Dateien tragen SPDX-Header gemäß REUSE-Standard:
# SPDX-FileCopyrightText: 2026 Friedhelm Matten / ISCaD GmbH
# SPDX-License-Identifier: EUPL-1.2
Siehe auch NOTICE für Hinweise zu Drittkomponenten und Trademark.
Wichtig: AION Clinical ist kein zertifiziertes Medizinprodukt nach MDR 2017/745. Nutzung in klinischen Entscheidungen über konkrete Patienten erfordert entweder eigene MDR-Zertifizierung des Betreibers oder ausschließliche Nutzung im Forschungs-Modus mit klinischer Aufsicht. Die Lizenz ändert daran nichts; siehe LICENSE Artikel 7+8 zum vollständigen Haftungsausschluss.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
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 aion_clinical-1.10.3.tar.gz.
File metadata
- Download URL: aion_clinical-1.10.3.tar.gz
- Upload date:
- Size: 264.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6dcc06b7d908771882b3ab82c58ea536d0ba807a1975b4bf5c0f712e661b5be4
|
|
| MD5 |
028b28113e67580ce66bcbfd4dfbf69a
|
|
| BLAKE2b-256 |
fbee999f64233706511c1a5a4f6fffc3430a06c3b98af15b9d742fe61405ce3b
|
File details
Details for the file aion_clinical-1.10.3-py3-none-any.whl.
File metadata
- Download URL: aion_clinical-1.10.3-py3-none-any.whl
- Upload date:
- Size: 171.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5b4d7ceb41bba6373a257db16af483abf5582803ffac57104b836d7bf86134a
|
|
| MD5 |
87c65e9e9e3df6b3a75d9c2e36120b3b
|
|
| BLAKE2b-256 |
0ce64807d0d175ce78aaf1e9c49c5ffaf10fec253c03868d495f93b2cc7913d8
|