Skip to main content

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:

  1. Typ-Hierarchie H = (T ∪ {⊤}, ≺) — DAG mit Eager-Validierung, transitive Hülle gecacht, Multi-Inheritance optional.
  2. 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.
  3. Allen-Algebra — alle 13 disjunkten Zeitintervall-Relationen, plus eine unscharfe Variante mit Monte-Carlo-Schätzung.
  4. Kausaler Graph — gerichteter azyklischer Graph mit do-Operator, Backdoor-Adjustierung nach Pearl, formaler d-Separations-Validierung.
  5. 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, Procedure
  • to_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.resources installiert 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: nur sqlite3 aus stdlib, keine SQLAlchemy.
  • GUI: PySide6 (Qt 6, LGPL), nicht PyQt6 (GPL) — kein Lizenzthema bei kommerzieller Weitergabe.
  • FuzzyAllenInterval: Monte-Carlo mit random.gauss, kein NumPy nötig.

Installation

Schritt-für-Schritt-Anleitung mit venv, allen Test- und GUI-Anweisungen: siehe BENUTZERHANDBUCH.md.

Empfohlen: lokale Python-Umgebung pro Projekt.

# venv anlegen und aktivieren
python3 -m venv venv
source venv/bin/activate          # Linux/macOS
# venv\Scripts\activate           # Windows

# Installation (eine der folgenden Varianten)
pip install -e .                  # Minimal (PyYAML + stdlib)
pip install -e ".[gui]"           # + PySide6 GUI
pip install -e ".[verify]"        # + Z3 SMT-Solver
pip install -e ".[gui,verify,dev]"  # Empfehlung für Entwicklung
pip install -e ".[all]"           # Alles inkl. fhir, causal, api

Python 3.10+ erforderlich. PySide6 ist nur nötig, wenn Du die GUI nutzen willst — Backend, Tests und Beispiele laufen auch ohne.

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

python examples/basic_usage.py            # Builder, Decorator, YAML
python examples/sqlite_demo.py            # Persistenz mit typisierten Refs
python examples/causal_inference_demo.py  # Backdoor-Adjustierung
python examples/phase_a_demo.py           # Knowledge-Graph + Pattern-Mining + Verify
python examples/fhir_demo.py              # FHIR-Bundle Round-Trip
python examples/cardiology_demo.py        # STEMI-Verlauf mit kombiniertem Schema

Erweiterungen (geplant / optional)

  • FHIR-Mapperaion.fhir: Round-Trip zwischen ClinicalEvent und fhir.resources.Observation etc.
  • DoWhy-Bridgeaion.causal.dowhy_bridge: CausalGraph → DoWhy zur Sensitivitätsanalyse.
  • REST-APIaion.api: FastAPI-Endpoints für Schema und Events.
  • Async-Streams — falls echte Echtzeit-Anbindung nötig wird, kann asyncio.Queue ohne Kafka eingesetzt werden.

Lizenz

AION Clinical wird unter Dual-Lizenz angeboten:

  1. EUPL-1.2 (Open Source) — European Union Public Licence v1.2. Volltext in LICENSE (deutsche Kurzfassung) und LICENSES/EUPL-1.2.txt (englische SPDX-Standardfassung).

  2. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aion_clinical-1.10.1.tar.gz (238.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aion_clinical-1.10.1-py3-none-any.whl (139.9 kB view details)

Uploaded Python 3

File details

Details for the file aion_clinical-1.10.1.tar.gz.

File metadata

  • Download URL: aion_clinical-1.10.1.tar.gz
  • Upload date:
  • Size: 238.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for aion_clinical-1.10.1.tar.gz
Algorithm Hash digest
SHA256 3906273a1ad4710965b75c358fc1d1191c54be7c072c9a7d3280d6682acf8158
MD5 0fc62708189eb9ca0f6114360d5c82c6
BLAKE2b-256 0e82aaa3e9d8cffd411ecd398f36e3994829e802774f2b0c8a22e8e71149df1f

See more details on using hashes here.

File details

Details for the file aion_clinical-1.10.1-py3-none-any.whl.

File metadata

  • Download URL: aion_clinical-1.10.1-py3-none-any.whl
  • Upload date:
  • Size: 139.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for aion_clinical-1.10.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1e5608e3c8a386c7f579a88af6f5223409f826a4e38a1516a90c35249d28bdd5
MD5 d256ee56537a883239d141d8785a3b8e
BLAKE2b-256 e4eef2c246d02bf68c70ff6a6ab6d8c49212ba163a6d05f0291949f86598d056

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page