Metadata-Version: 2.4
Name: aion-clinical
Version: 1.10.3
Summary: Formal temporal and causal structure for consistent clinical data across systems (HL7 v2, FHIR, MLLP). EUPL-1.2 / commercial dual license.
Author-email: Friedhelm Matten <licensing@iscad-it.de>
Maintainer-email: ISCaD GmbH <licensing@iscad-it.de>
License: EUPL-1.2
Project-URL: Source, https://codeberg.org/iscad/aion
Project-URL: PyPI, https://pypi.org/project/aion-clinical/
Project-URL: Changelog, https://pypi.org/project/aion-clinical/#history
Project-URL: Theoretical Foundation, https://doi.org/10.5281/zenodo.19548857
Keywords: clinical,healthcare,medical-informatics,ontology,causal-inference,temporal-logic,fhir,hl7,mllp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: PyYAML>=6.0
Provides-Extra: numeric
Requires-Dist: numpy>=1.24; extra == "numeric"
Provides-Extra: gui
Requires-Dist: PySide6>=6.5; extra == "gui"
Provides-Extra: fhir
Requires-Dist: fhir.resources>=7.0; extra == "fhir"
Provides-Extra: causal
Requires-Dist: dowhy>=0.11; extra == "causal"
Requires-Dist: numpy>=1.24; extra == "causal"
Requires-Dist: pandas>=2.0; extra == "causal"
Provides-Extra: dowhy
Requires-Dist: dowhy>=0.11; extra == "dowhy"
Requires-Dist: numpy>=1.24; extra == "dowhy"
Requires-Dist: pandas>=2.0; extra == "dowhy"
Provides-Extra: notebook
Requires-Dist: jupyter>=1.0; extra == "notebook"
Requires-Dist: ipython>=8.0; extra == "notebook"
Requires-Dist: matplotlib>=3.5; extra == "notebook"
Requires-Dist: networkx>=3.0; extra == "notebook"
Provides-Extra: api
Requires-Dist: fastapi>=0.100; extra == "api"
Requires-Dist: uvicorn>=0.22; extra == "api"
Provides-Extra: verify
Requires-Dist: z3-solver>=4.12; extra == "verify"
Provides-Extra: ldap
Requires-Dist: ldap3>=2.9; extra == "ldap"
Provides-Extra: oidc
Requires-Dist: authlib>=1.3; extra == "oidc"
Requires-Dist: requests>=2.31; extra == "oidc"
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.5; extra == "dev"
Provides-Extra: all
Requires-Dist: aion-clinical[api,causal,fhir,gui,ldap,numeric,oidc,verify]; extra == "all"
Dynamic: license-file

# 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

### Endanwender — von PyPI

```bash
# 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:

```bash
aion --version              # → aion 1.10.3
python -m aion.examples.basic_usage
```

### Entwickler — aus dem Source-Repository

```bash
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.md` ist in der Source-Distribution
> enthalten (`pip download aion-clinical --no-binary :all:`) oder im
> Codeberg-Repo verfügbar.

## Schnellstart

```python
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

```bash
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:

```python
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

```bash
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:

```python
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:

```bash
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 zwischen `ClinicalEvent` und
  `fhir.resources.Observation` etc.
- **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.Queue` ohne 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`](MIGRATION.md) (in der Source-Distribution oder im
Codeberg-Repo).

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