Commit ece87732 authored by Sebastian Mate's avatar Sebastian Mate
Browse files

Add "Implementation status" notes

Get Medication and MedicationStatement working again for MII profiles
Various changes to get MII FHIR data fully working
parent ea3fb6c6
......@@ -32,6 +32,30 @@
-- - Fix calculation of patient's age in PATIENT_DIMENSION
-- - Extended ENCOUTNER_MAPPING, distinction between true encounter (CASE) and stay on a ward (WARD)
-- - Populate VISIT_DIMENSION with basic visit data
-- 2021-06-11: - Add "Implementation status" notes
-- - Get Medication and MedicationStatement working again for MII profiles
-- - Various changes to get MII FHIR data fully working
/*
Implementation status:
======================
Resource Type P21 Profile MII Profile GECCO Profile Notes
---------------------------------------------------------------------------------------------------------------------
Composition N/A Not Implemented N/A Kommt aus NLP. Alle Diagnosen eines Arztbriefes.
Condition OK Keine Fallnummer bei NLP?
Device N/A Not Implemented N/A Nicht relevant, sagt nur "Averbis Health Discovery".
DiagnosticReport N/A OK Nutzen fraglich!
Encounter OK OK Noch keine Verlegungskette!
Location N/A Not Implemented N/A Nicht relevant für i2b2
Medication OK* (* Getestet mit einer Ressource)
MedicationStatement OK* (* Getestet mit einer Ressource)
Observation OK
Patient OK OK
Procedure OK
ServiceRequest
*/
-- ============= Create Basic Tables =============
......@@ -207,11 +231,11 @@ begin
FHIR_resourcetype != 'Encounter' and
FHIR_resourcetype != 'Condition' and
FHIR_resourcetype != 'Observation' and
FHIR_resourcetype != 'Immunization' and -- TODO
FHIR_resourcetype != 'Consent' and -- TODO
FHIR_resourcetype != 'Immunization' and
FHIR_resourcetype != 'Consent' and
FHIR_resourcetype != 'Procedure' and
FHIR_resourcetype != 'Medication' and
-- FHIR_resourcetype != 'MedicationStatement' and
FHIR_resourcetype != 'MedicationStatement' and
FHIR_resourcetype != 'ServiceRequest' and -- Ignored, not useful for i2b2.
FHIR_resourcetype != 'DiagnosticReport'
then raise exception 'Resource type "%" not supported.', FHIR_resourcetype; end if;
......@@ -251,6 +275,9 @@ begin
if FHIR_encounter_identifier is null then raise exception 'FHIR_encounter_identifier is empty!'; end if;
else
FHIR_encounter_identifier := fhir->'encounter'->'identifier'->>'value';
if FHIR_encounter_identifier is null then
FHIR_encounter_identifier := fhir->'encounter'->>'reference';
end if;
end if;
--
if FHIR_resourcetype = 'MedicationStatement' then
......@@ -262,6 +289,8 @@ begin
perform i2b2miracum.fhir_elt_log('FHIR_patient_identifier = ' || FHIR_patient_identifier);
perform i2b2miracum.fhir_elt_log('FHIR_encounter_identifier = ' || FHIR_encounter_identifier);
--
--return;
--
-- *** Handle i2b2 PATIENT data / references ***
--
-- Check if the patient is already known in i2b2:
......@@ -351,6 +380,8 @@ begin
end if;
end if;
--
-- return;
--
-- *** Handle i2b2 ENCOUNTER data / references ***
--
if FHIR_resourcetype != 'Patient' then
......@@ -396,48 +427,52 @@ begin
1 -- upload_id
);
--
perform i2b2miracum.fhir_elt_log('Inserting into VISIT_DIMENSION.');
-- Populate ENCOUNTER_MAPPING:
--
-- https://community.i2b2.org/wiki/display/ServerSideDesign/VISIT_DIMENSION+Table
if fhir->'period'->>'start' is not null then
FHIR_encounter_ACTIVE_STATUS_CD_scndChar := 'I';
else
FHIR_encounter_ACTIVE_STATUS_CD_scndChar := 'L';
end if;
--
if fhir->'period'->>'end' is not null then
FHIR_encounter_ACTIVE_STATUS_CD_firstChar := 'T';
else
FHIR_encounter_ACTIVE_STATUS_CD_firstChar := 'U';
end if;
--
insert into i2b2miracum.visit_dimension (encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, location_path, length_of_stay, visit_blob, update_date, download_date, import_date, sourcesystem_cd, upload_id)
values (i2b2_encounter_identifier, -- encounter_num
i2b2_patient_identifier, -- patient_num
FHIR_encounter_ACTIVE_STATUS_CD_firstChar || FHIR_encounter_ACTIVE_STATUS_CD_scndChar, -- active_status_cd
(fhir->'period'->>'start')::timestamp, -- start_date
(fhir->'period'->>'end')::timestamp, -- end_date
case when fhir->'class'->>'code' = 'IMP' then 'I' --P21
when fhir->'class'->>'code' = 'OUT' then 'O'
when fhir->'class'->>'code' = 'stationaer' then 'I' --MII
when fhir->'class'->>'code' = 'teilstationaer' then 'I' -- (Info von Detlef)
when fhir->'class'->>'code' = 'ambulant' then 'O'
else fhir->'class'->>'code' end, -- inout_cd
null, -- location_cd
null, -- location_path
null, -- length_of_stay -- ??? TODO
FHIR_id, -- visit_blob
now(), -- update_date
now(), -- download_date
now(), -- import_date
FHIR_sourcesystem, -- sourcesystem_cd
1 -- upload_id
);
if FHIR_resourcetype = 'Encounter' then
perform i2b2miracum.fhir_elt_log('Inserting into VISIT_DIMENSION.');
-- Populate ENCOUNTER_MAPPING:
--
-- https://community.i2b2.org/wiki/display/ServerSideDesign/VISIT_DIMENSION+Table
if fhir->'period'->>'start' is not null then
FHIR_encounter_ACTIVE_STATUS_CD_scndChar := 'I';
else
FHIR_encounter_ACTIVE_STATUS_CD_scndChar := 'L';
end if;
--
if fhir->'period'->>'end' is not null then
FHIR_encounter_ACTIVE_STATUS_CD_firstChar := 'T';
else
FHIR_encounter_ACTIVE_STATUS_CD_firstChar := 'U';
end if;
--
insert into i2b2miracum.visit_dimension (encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, location_path, length_of_stay, visit_blob, update_date, download_date, import_date, sourcesystem_cd, upload_id)
values (i2b2_encounter_identifier, -- encounter_num
i2b2_patient_identifier, -- patient_num
FHIR_encounter_ACTIVE_STATUS_CD_firstChar || FHIR_encounter_ACTIVE_STATUS_CD_scndChar, -- active_status_cd
(fhir->'period'->>'start')::timestamp, -- start_date
(fhir->'period'->>'end')::timestamp, -- end_date
case when fhir->'class'->>'code' = 'IMP' then 'I' --P21
when fhir->'class'->>'code' = 'OUT' then 'O'
when fhir->'class'->>'code' = 'stationaer' then 'I' --MII
when fhir->'class'->>'code' = 'teilstationaer' then 'I' -- (Info von Detlef)
when fhir->'class'->>'code' = 'ambulant' then 'O'
else fhir->'class'->>'code' end, -- inout_cd
null, -- location_cd
null, -- location_path
null, -- length_of_stay -- ??? TODO
FHIR_id, -- visit_blob
now(), -- update_date
now(), -- download_date
now(), -- import_date
FHIR_sourcesystem, -- sourcesystem_cd
1 -- upload_id
);
end if;
end if;
end if;
end if;
--
--return;
--
-- *** Handle various types of resources ***
--
if FHIR_resourcetype = 'Observation'
......@@ -446,7 +481,7 @@ begin
or FHIR_resourcetype = 'Consent'
or FHIR_resourcetype = 'Immunization'
or FHIR_resourcetype = 'DiagnosticReport'
or FHIR_resourcetype = 'MedicationStatement'
--or FHIR_resourcetype = 'MedicationStatement'
then
-- Delete previous data:
perform i2b2miracum.fhir_elt_log('Deleting previous entries in OBSERVATION_FACT.');
......@@ -498,7 +533,6 @@ begin
nextval('instance_num_seq') -- text_search_index
from (select * from i2b2miracum.select_fhir_fields(fhir)) as fhir_data;
end if;
/*
--
-- *** Handle FHIR MEDICATION resource ***
--
......@@ -520,11 +554,12 @@ begin
from (select fhir) new_as_table
) fhir_data;
-- Update old MedicationStatement data in OBSERVATION_FACT
perform i2b2miracum.fhir_elt_log('Updating old MedicationStatement data in OBSERVATION_FACT.');
-- Move the old OBSERVATION_FACT entry (MedicationStatement data) to OBSERVATION_FACT_TEMP:
insert into i2b2miracum.observation_fact_temp (select * from i2b2miracum.observation_fact where fhir_reference = 'Medication/' || FHIR_id);
delete from i2b2miracum.observation_fact where fhir_reference = 'Medication/' || FHIR_id;
insert into i2b2miracum.observation_fact (
select oft.encounter_num,
select oft.encounter_num,
oft.patient_num,
i2b2miracum.get_system_abbrv(fm.system) || ':' || fm.code, -- concept_cd
oft.provider_id,
......@@ -567,16 +602,15 @@ begin
insert into i2b2miracum.observation_fact (encounter_num, patient_num, concept_cd, provider_id, start_date, modifier_cd, instance_num, valtype_cd, tval_char, nval_num, valueflag_cd, quantity_num, units_cd, end_date, location_cd, observation_blob, confidence_num, update_date, download_date, import_date, sourcesystem_cd, upload_id, text_search_index, fhir_reference)
select i2b2_encounter_identifier, -- encounter_num
i2b2_patient_identifier, -- patient_num
case when fhir_data.medicationCodeableConcept_coding_code is not null then
i2b2miracum.get_system_abbrv(fhir_data.medicationCodeableConcept_coding_system) || ':' || fhir_data.medicationCodeableConcept_coding_code
when fhir_data.medication_code is not null then
i2b2miracum.get_system_abbrv(fhir_data.medication_system) || ':' || fhir_data.medication_code
case when fhir_medication.code is not null then
i2b2miracum.get_system_abbrv(fhir_medication.system) || ':' || fhir_medication.code -- already have actual type of medication, use data from left join
else
'Medication'
end,
'Medication' -- do not have actual type of medication yet, create a temporary entry
end, -- concept_cd
'FHIR', -- provider_id
case when fhir_data.effectiveDateTime is not null then fhir_data.effectiveDateTime
else '-infinity'::timestamptz end, -- start_date
case when fhir_data.StartTimes is not null then fhir_data.StartTimes
else '-infinity'::timestamptz
end, -- start_date
'@', -- modifier_cd
nextval('instance_num_seq'), -- instance_num
'@', -- valtype_cd
......@@ -585,8 +619,9 @@ begin
null, -- valueflag_cd
null, -- quantity_num
null, -- units_cd
case when fhir_data.effectiveDateTime is not null then fhir_data.effectiveDateTime
else '-infinity'::timestamptz end, -- end_date
case when fhir_data.StartTimes is not null then fhir_data.StartTimes
else '-infinity'::timestamptz
end, -- end_date
'', -- location_cd
FHIR_id, -- observation_blob
0, -- confidence_num
......@@ -596,12 +631,11 @@ begin
FHIR_sourcesystem, -- sourcesystem_cd
1, -- upload_id
nextval('instance_num_seq'), -- text_search_index
medication_reference -- fhir_reference
from (select * from i2b2miracum.select_fhir_fields(fhir)) as fhir_data;
fhirReference -- fhir_reference
from (select * from i2b2miracum.select_fhir_fields(fhir)) as fhir_data
left join i2b2miracum.fhir_medication on fhir_data.fhirReference = 'Medication/' || fhir_medication.id;
end if;
*/
--
--return null; -- Return nothing. This prevents that the FHIR data is actually written into the "FHIR" table.
exception
when others then
get stacked diagnostics
......@@ -617,6 +651,7 @@ exception
end;
$$;
drop function i2b2miracum.select_fhir_fields;
create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
returns table (ID text,
StartTimes timestamp,
......@@ -629,7 +664,8 @@ create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
valueQuantity_value numeric(18, 5),
valueQuantity_unit text,
valueQuantity_system text,
valueQuantity_code text)
valueQuantity_code text,
fhirReference text)
as $$ begin return query
with FhirDataAsTable(fhir2) as (select fhir)
select
......@@ -644,7 +680,8 @@ create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
valueQuantity_value2::numeric(18, 5) as valueQuantity_valuenumeric,
valueQuantity_unit2::text as valueQuantity_unit,
valueQuantity_system2::text as valueQuantity_system,
valueQuantity_code2::text as valueQuantity_code
valueQuantity_code2::text as valueQuantity_code,
fhirReference2::text as fhirReference
from FhirDataAsTable
left join (-- ======== Below code fetches start and end times (columns start_date and end_date) ========
select (fhir2->>'performedDateTime')::text as StartTimes2
......@@ -657,6 +694,9 @@ create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
from FhirDataAsTable
union
select (fhir2->'occurrenceDateTime' /*|| 'T00:00:00+00:00'*/)::text as StartTimes2
from FhirDataAsTable
union
select (fhir2->>'dateAsserted')::text as StartTimes2
from FhirDataAsTable
) as sq1 on true and StartTimes2 is not null
left join (select (fhir2->>'performedDateTime')::text as EndTimes2
......@@ -670,6 +710,9 @@ create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
union
select (fhir2->>'occurrenceDateTime' /*|| 'T00:00:00+00:00'*/)::text as EndTimes2
from FhirDataAsTable
union
select (fhir2->>'dateAsserted')::text as EndTimes2
from FhirDataAsTable
) as sq2 on true and EndTimes2 is not null
left join (-- ======== Below code fetches the values that go into the i2b2 concept code (column concept_cd) ========
select jsonb_array_elements(fhir2->'code'->'coding')->>'code' as MainCode2,
......@@ -790,11 +833,15 @@ create or replace function i2b2miracum.select_fhir_fields(fhir jsonb)
from FhirDataAsTable
) as sq4 on true and ModifierSystem2 is not null and ModifierCode2 is not null
left join (-- ======== Below code fetches data for other columns ========
select (fhir2->'valueQuantity'->>'value')::numeric(18,5) as valueQuantity_value2, -- Numeric values for GECCO Observation
select (fhir2->'valueQuantity'->>'value')::numeric(18,5) as valueQuantity_value2, -- Numeric values for GECCO Observation
fhir2->'valueQuantity'->>'unit'::text as valueQuantity_unit2,
fhir2->'valueQuantity'->>'system'::text as valueQuantity_system2,
fhir2->'valueQuantity'->>'code'::text as valueQuantity_code2
from FhirDataAsTable) as sq5 on true;
from FhirDataAsTable) as sq5 on true
left join (-- ======== Below code fetches references to other fhir resources ========
select (fhir2->'medicationReference'->>'reference')::text as fhirReference2
from FhirDataAsTable) as sq6 on true;
--
end $$ language plpgsql;
-- Connect trigger and function:
......@@ -839,3 +886,4 @@ INSERT INTO i2b2miracum.fhir (fhir) VALUES ('{"id": "Medication1", "code": {"cod
INSERT INTO i2b2miracum.fhir (fhir) VALUES ('{"id": "MedicationStatement1", "meta": {"profile": ["https://www.medizininformatik-initiative.de/fhir/core/StructureDefinition/MedicationStatement"], "security": [{"code": "PSEUDED", "system": "http://terminology.hl7.org/CodeSystem/v3-ObservationValue", "display": "part of the resource is pseudonymized"}]}, "dosage": [{"text": "Cisplatin (50 mg/m²", "doseAndRate": [{"doseQuantity": {"unit": "mg/m²", "value": 50.0}}]}], "status": "unknown", "context": {"type": "Encounter", "reference": "Encounter/XXXXXXXXXXXXX", "identifier": {"type": {"text": "Visit number", "coding": [{"code": "VN", "system": "http://terminology.hl7.org/CodeSystem/v2-0203"}]}, "value": "Encounter4", "system": "https://fhir.diz.uk-erlangen.de/NamingSystem/encounterId"}}, "subject": {"type": "Patient", "reference": "Patient/XXXXXXXXXXXXXXX", "identifier": {"type": {"text": "Medical record number", "coding": [{"code": "MR", "system": "http://terminology.hl7.org/CodeSystem/v2-0203"}]}, "value": "Patient4", "system": "https://fhir.diz.uk-erlangen.de/NamingSystem/patientId"}}, "identifier": [{"value": "Cisplatin_50.0mg/m²_208004", "system": "https://averbis.com/de.averbis.types.health.Medication"}], "dateAsserted": "2008-07-29T17:44:00+00:00", "resourceType": "MedicationStatement", "effectiveDateTime": "2008-07-29T17:44:00+00:00", "medicationReference": {"type": "Medication", "reference": "Medication/Medication1", "identifier": {"value": "Cisplatin_50.0mg/m²", "system": "https://averbis.com/de.averbis.types.health.Medication"}}}');
*/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment