medizininformatik-initiative / INTERPOLAR

CDS Tool Chain Repository
https://medizininformatik-initiative.github.io/INTERPOLAR/
4 stars 0 forks source link

cds2db bessere Dokumentation/log #289

Closed KoesterH closed 2 weeks ago

KoesterH commented 2 weeks ago

Im Vergleich zu dem ersten Release ist die Befüllung der Datenbank komplexer geworden und ich kann momentan nicht wirklich nachvollziehen wie es genau funktioniert. Bei ersten Tests auf dem Leipziger Test-Server (mit Daten in der Vergangenheit) werden Daten geladen, in cds2db_in gespeichert aber am Ende ist die Tabelle cds2db_in trotzdem leer. Lediglich in db_log finden sich Daten. Beim ersten Ausprobieren auf unseren Polar Daten findet das Skript initial korrekt Encounter im angegebenen Zeitraum allerdings keine weiteren Ressourcen. Es wird auch nichts in die Datenbank geschrieben. Es wäre hilfreich, wenn in den logs neben der initial Abfrage auch die Folgeabfragen (wenigstens immer eine pro Abfrageblock) ausgegeben werden. Es gibt in dem Ordner R-cds2db einen outputLocal sowie outputGlobal Ordner. Die bleiben bei mir immer leer? Falls da log Dateien erzeugt werden sollten, funktioniert das nicht. Generell wäre eine bessere Erklärung zu der Funktionsweise der Strecke hilfreich, um Fehler besser eingrenzen zu können.

astruebi commented 2 weeks ago

Erst sage ich etwas zum Datenfluss, danach zum Logging. Die Doku zum genauen Datenbank-internen Ablauf wird in den nächsten Tagen bereit gestellt.

Datenfluss

Es ist korrekt, dass am Ende nur Daten in den Tabellen des Schemas "db_log" stehen. Das gilt sowohl für das Modul "cds2db" als auch für das Modul "dataprocessor".

Modul "cds2db"

Jetzt funktioniert es so, dass zuerst über das Schema "cds2db_in" Daten in dessen Tabellen mit dem Suffix "_raw" geschrieben werden. Die Tabellen heißen wie die FHIR-Ressourcen, außer die spezielle Tabelle "pids_per_ward_raw", die die aktuellen Patienten IDs der Interpolarstationen speichert. Danach läuft jede Minute ein Cron-Job und kopiert die Daten in die gleich heißenden Tabellen des "db_log" Schemas und entfernt sie aus den Tabellen des "cds2db" Schemas. Dabei wird geprüft, ob derselbe Datensatz bereits in den Tabellen des "db_log" vorkommt. Wenn nicht, wird er hinzugefügt und der Zeitstempel "input_datetime" mit dem aktuellen Datum gesetzt. Wenn er bereits enthalten war, wird nur die Spalte "last_check_datetime" auf das aktuelle Datum gesetzt.

Nach dem Cron-Job stehen nur noch Daten in "db_log" Tabellen.

Dieses Vorgehen stellt sicher, dass wir alle Datensätze haben, aber eben nur ein mal und wissen, wann wir den Datensatz das erste und das letzte Mal gesehen haben.

Die RAW-Daten sind genau die vom FHIR-Server heruntergeladenen Ressourcen, die nur durch den fhircrackr geleitet wurden. Also die größtmöglich unveränderten Daten vom Server.

Nach dem Schreiben der RAW-Daten in die Datenbank durch das R-Script wartet das Script ca. 1 Minute, um sicher zu stellen, dass der oben genannte Cron-Job mit dem "Rüberkopieren" in den Kern der Datenbank gelaufen ist.

Danach macht das R-Script damit weiter, mit dem Schema "cds2db_out" über Views alle neuen RAW-Daten aus den "db_log"-Tabellen abzurufen. Neu heißt, dass der nun folgende Zerlegungs- und Typisierungsprozess diese Daten noch nicht zerlegt und typisiert hat, was an den jeweiligen primary keys der Ursprungsdaten erkannt wird.

Diese Zerlegung ist ein Prozess, der im fhircrackr fhir_melt() heißt. Das Problem ist, dass in den RAW-Daten nach dem fhir_crack() alle Ressourcen immer genau nur 1 Zeile in der Tabelle der jeweiligen Ressource einnehmen. Wenn diese Ressource aber eine Liste von Unterelementen hat (z.B. Encounter hat eine Liste von Referenzen auf mehrere Diagnosen (Conditions)), dann stehen diese mit einer speziellen Klammerung und in den Klammern enthaltenen Indizes durch Tilde (" ~ ") getrennt in der zugehörigen Spalte.

Diese Klammerung und Indizes müssen nun alle in eigene Zeilen aufgespaltet werden. Dabei werden alle anderen Daten der Zeile jeweils dupliziert. Da diese Listen an vielen Stellen auftauchen, der Vorgang generisch umgesetzt ist und dieses fhir_melt() eine recht teure Operation ist, dauert dieser Vorgang unter Umständen etwas länger.

Wenn alle Listen in eigene Zeilen zerlegt sind, dann können sie typisiert werden. Bis jetzt sind alle Daten Strings (bzw. in R character). Anhand der TableDescription-Excel-Tabelle werden nun alle nicht-String-Daten in Zahlen, Datumsangaben, Uhrzeiten usw. umgewandelt.

Nach der Umwandlung werden die nun fertig aufbereiteten Daten wieder über das Schema "cds2db_in" in die Tabellen ohne den "_raw"-Suffix geschrieben. Auch hier geht wieder jede Minute ein Cron-Job los, der die Daten in den Kern der Datenbank ("db_log") in die gleich heißenden Tabellen verschiebt.

Damit ist das Modul "cds2db" fertig und der "dataprocessor" kann starten (allerdings sollte dazwischen auch mind. 1 Minute liegen, damit die Daten zuverlässig im Kern vorliegen).

Modul "dataprocessor"

Der Dataprocessor erstellt aus den vom "cds2db" Modul erstellten Tabellen die Ausgabetabellen für das Modul "frontend". Im Moment sind das die Tabellen "patient_fe" und "fall_fe". Auch hier werden die Tabellen wieder durch einen Cron-Job in den Kern ("db_log") in Tabellen mit demselben Namen kopiert. Nur dort kann man nach den Cron-Jobs Daten finden.

Die Tabelle "patient_fe" sollte alle Patienten enthalten, deren FHIR-interne ID in den Eingangsdaten vorhanden war.

Die Tabelle "fall_fe" sollte eine Liste aller Fälle enthalten, die für Patienten mit den oben genannten IDs aktuell laufen.

Voraussetzung: Das aktuelle Datum muss zu den Start- und Enddaten der Encounter passen. Es werden nur Fälle gefunden, deren Startdatum vor dem aktuellen Datum liegt und deren Enddatum nach dem aktuellen Datum liegt oder nicht gesetzt ist.

Will man hier für Daten aus der Vergangenheit irgendwas sehen, dann muss in der Konfigurationsdatei für den Dataprocessor (dataprocessor_cofig.toml) unter der Variable DEBUG_CURRENT_DATETIME ein entsprechend zu den Daten passendes Datum eingestellt werden. Alle Variablen, die im Echtbetrieb deaktiviert sein sollten, haben den Präfix "DEBUG_".

Logging

Das Logging funktioniert eigentlich recht gut. Es werden alle DB-Anfragen geloggt. Aber gerade wird es tatsächlich nicht rausgeschrieben aus dem Docker. Wir werden das schnellstmöglich fixen.

KoesterH commented 2 weeks ago

Vielen Dank für die gute Erklärung :-)

astruebi commented 2 weeks ago

Wir haben gerade ein neues Release v0.2.1 mit dem Hotfix für das Logging erstellt.