From 0e505d84d80e04a7f188d8e6a38a5f313b08cb11 Mon Sep 17 00:00:00 2001 From: that-guy-is-it Date: Wed, 18 Nov 2020 11:42:14 -0500 Subject: [PATCH] API-2834 observation synthetic data (#10) --- .../patientgenerateddata/Populaterator.java | 34 +++++- .../src/test/resources/observation/ekg.json | 111 ++++++++++++++++++ .../src/test/resources/observation/sat02.json | 97 +++++++++++++++ .../3141.json | 0 .../f201.json | 0 .../db/changelog/db.changelog-master.yaml | 25 ++++ 6 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 patient-generated-data-synthetic/src/test/resources/observation/ekg.json create mode 100644 patient-generated-data-synthetic/src/test/resources/observation/sat02.json rename patient-generated-data-synthetic/src/test/resources/{questionnaireResponse => questionnaire-response}/3141.json (100%) rename patient-generated-data-synthetic/src/test/resources/{questionnaireResponse => questionnaire-response}/f201.json (100%) diff --git a/patient-generated-data-synthetic/src/test/java/gov/va/api/health/patientgenerateddata/Populaterator.java b/patient-generated-data-synthetic/src/test/java/gov/va/api/health/patientgenerateddata/Populaterator.java index 2ea3b90a..2eadd857 100644 --- a/patient-generated-data-synthetic/src/test/java/gov/va/api/health/patientgenerateddata/Populaterator.java +++ b/patient-generated-data-synthetic/src/test/java/gov/va/api/health/patientgenerateddata/Populaterator.java @@ -4,6 +4,7 @@ import static java.util.stream.Collectors.joining; import com.fasterxml.jackson.databind.ObjectMapper; +import gov.va.api.health.r4.api.resources.Observation; import gov.va.api.health.r4.api.resources.Questionnaire; import gov.va.api.health.r4.api.resources.QuestionnaireResponse; import java.io.File; @@ -95,6 +96,31 @@ public static void main(String[] args) { } } + @SneakyThrows + public static void observation(@NonNull Connection connection) { + Set ids = new HashSet<>(); + + for (File f : new File(baseDir() + "/src/test/resources/observation").listFiles()) { + Observation observation = MAPPER.readValue(f, Observation.class); + Set> violations = + Validation.buildDefaultValidatorFactory().getValidator().validate(observation); + checkState(violations.isEmpty(), "Invalid payload: " + violations); + + String id = observation.id(); + checkState(id != null); + checkState(!ids.contains(id), "Duplicate ID " + id); + ids.add(id); + + String sqlInsert = sqlInsert("app.Observation", List.of("id", "payload", "version")); + try (PreparedStatement statement = connection.prepareStatement(sqlInsert)) { + statement.setObject(1, id); + statement.setObject(2, MAPPER.writeValueAsString(observation)); + statement.setObject(3, 0); + statement.execute(); + } + } + } + @SneakyThrows private static void populate(@NonNull Db db) { log("Populating " + db.name()); @@ -102,6 +128,7 @@ private static void populate(@NonNull Db db) { bootstrap(db); liquibase(db); var connection = db.connection(); + observation(connection); questionnaire(connection); questionnaireResponse(connection); connection.commit(); @@ -112,6 +139,7 @@ private static void populate(@NonNull Db db) { @SneakyThrows private static void questionnaire(@NonNull Connection connection) { Set ids = new HashSet<>(); + for (File f : new File(baseDir() + "/src/test/resources/questionnaire").listFiles()) { Questionnaire questionnaire = MAPPER.readValue(f, Questionnaire.class); Set> violations = @@ -126,7 +154,7 @@ private static void questionnaire(@NonNull Connection connection) { String sqlInsert = sqlInsert("app.Questionnaire", List.of("id", "payload", "version")); try (PreparedStatement statement = connection.prepareStatement(sqlInsert)) { statement.setObject(1, id); - statement.setObject(2, new ObjectMapper().writeValueAsString(questionnaire)); + statement.setObject(2, MAPPER.writeValueAsString(questionnaire)); statement.setObject(3, 0); statement.execute(); } @@ -137,7 +165,7 @@ private static void questionnaire(@NonNull Connection connection) { private static void questionnaireResponse(@NonNull Connection connection) { Set ids = new HashSet<>(); - for (File f : new File(baseDir() + "/src/test/resources/questionnaireResponse").listFiles()) { + for (File f : new File(baseDir() + "/src/test/resources/questionnaire-response").listFiles()) { QuestionnaireResponse response = MAPPER.readValue(f, QuestionnaireResponse.class); Set> violations = Validation.buildDefaultValidatorFactory().getValidator().validate(response); @@ -152,7 +180,7 @@ private static void questionnaireResponse(@NonNull Connection connection) { sqlInsert("app.QuestionnaireResponse", List.of("id", "payload", "version")); try (PreparedStatement statement = connection.prepareStatement(sqlInsert)) { statement.setObject(1, id); - statement.setObject(2, new ObjectMapper().writeValueAsString(response)); + statement.setObject(2, MAPPER.writeValueAsString(response)); statement.setObject(3, 0); statement.execute(); } diff --git a/patient-generated-data-synthetic/src/test/resources/observation/ekg.json b/patient-generated-data-synthetic/src/test/resources/observation/ekg.json new file mode 100644 index 00000000..f277ee91 --- /dev/null +++ b/patient-generated-data-synthetic/src/test/resources/observation/ekg.json @@ -0,0 +1,111 @@ +{ + "resourceType" : "Observation", + "id" : "ekg", + "text" : { + "status" : "generated", + "div" : "

Generated Narrative with Details

id: ekg

status: final

category: Procedure (Details : {http://terminology.hl7.org/CodeSystem/observation-category code 'procedure' = 'Procedure', given as 'Procedure'})

code: MDC_ECG_ELEC_POTL (Details : {urn:oid:2.16.840.1.113883.6.24 code '131328' = '131328', given as 'MDC_ECG_ELEC_POTL'})

subject: P. van de Heuvel

effective: 19/02/2015 9:30:35 AM

performer: A. Langeveld

device: 12 lead EKG Device Metric

component

code: MDC_ECG_ELEC_POTL_I (Details : {urn:oid:2.16.840.1.113883.6.24 code '131329' = '131329', given as 'MDC_ECG_ELEC_POTL_I'})

value: Origin: (system = '[not stated]' code null = 'null'), Period: 10, Factor: 1.612, Lower: -3300, Upper: 3300, Dimensions: 1, Data: 2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073

component

code: MDC_ECG_ELEC_POTL_II (Details : {urn:oid:2.16.840.1.113883.6.24 code '131330' = '131330', given as 'MDC_ECG_ELEC_POTL_II'})

value: Origin: (system = '[not stated]' code null = 'null'), Period: 10, Factor: 1.612, Lower: -3300, Upper: 3300, Dimensions: 1, Data: 2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073

component

code: MDC_ECG_ELEC_POTL_III (Details : {urn:oid:2.16.840.1.113883.6.24 code '131389' = '131389', given as 'MDC_ECG_ELEC_POTL_III'})

value: Origin: (system = '[not stated]' code null = 'null'), Period: 10, Factor: 1.612, Lower: -3300, Upper: 3300, Dimensions: 1, Data: 2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073

" + }, + "status" : "final", + "category" : [ + { + "coding" : [ + { + "system" : "http://terminology.hl7.org/CodeSystem/observation-category", + "code" : "procedure", + "display" : "Procedure" + } + ] + } + ], + "code" : { + "coding" : [ + { + "system" : "urn:oid:2.16.840.1.113883.6.24", + "code" : "131328", + "display" : "MDC_ECG_ELEC_POTL" + } + ] + }, + "subject" : { + "reference" : "Patient/f001", + "display" : "P. van de Heuvel" + }, + "effectiveDateTime" : "2015-02-19T09:30:35+01:00", + "performer" : [ + { + "reference" : "Practitioner/f005", + "display" : "A. Langeveld" + } + ], + "device" : { + "display" : "12 lead EKG Device Metric" + }, + "component" : [ + { + "code" : { + "coding" : [ + { + "system" : "urn:oid:2.16.840.1.113883.6.24", + "code" : "131329", + "display" : "MDC_ECG_ELEC_POTL_I" + } + ] + }, + "valueSampledData" : { + "origin" : { + "value" : 2048 + }, + "period" : 10, + "factor" : 1.612, + "lowerLimit" : -3300, + "upperLimit" : 3300, + "dimensions" : 1, + "data" : "2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073" + } + }, + { + "code" : { + "coding" : [ + { + "system" : "urn:oid:2.16.840.1.113883.6.24", + "code" : "131330", + "display" : "MDC_ECG_ELEC_POTL_II" + } + ] + }, + "valueSampledData" : { + "origin" : { + "value" : 2048 + }, + "period" : 10, + "factor" : 1.612, + "lowerLimit" : -3300, + "upperLimit" : 3300, + "dimensions" : 1, + "data" : "2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073" + } + }, + { + "code" : { + "coding" : [ + { + "system" : "urn:oid:2.16.840.1.113883.6.24", + "code" : "131389", + "display" : "MDC_ECG_ELEC_POTL_III" + } + ] + }, + "valueSampledData" : { + "origin" : { + "value" : 2048 + }, + "period" : 10, + "factor" : 1.612, + "lowerLimit" : -3300, + "upperLimit" : 3300, + "dimensions" : 1, + "data" : "2041 2043 2037 2047 2060 2062 2051 2023 2014 2027 2034 2033 2040 2047 2047 2053 2058 2064 2059 2063 2061 2052 2053 2038 1966 1885 1884 2009 2129 2166 2137 2102 2086 2077 2067 2067 2060 2059 2062 2062 2060 2057 2045 2047 2057 2054 2042 2029 2027 2018 2007 1995 2001 2012 2024 2039 2068 2092 2111 2125 2131 2148 2137 2138 2128 2128 2115 2099 2097 2096 2101 2101 2091 2073 2076 2077 2084 2081 2088 2092 2070 2069 2074 2077 2075 2068 2064 2060 2062 2074 2075 2074 2075 2063 2058 2058 2064 2064 2070 2074 2067 2060 2062 2063 2061 2059 2048 2052 2049 2048 2051 2059 2059 2066 2077 2073" + } + } + ] +} diff --git a/patient-generated-data-synthetic/src/test/resources/observation/sat02.json b/patient-generated-data-synthetic/src/test/resources/observation/sat02.json new file mode 100644 index 00000000..4b49d0d9 --- /dev/null +++ b/patient-generated-data-synthetic/src/test/resources/observation/sat02.json @@ -0,0 +1,97 @@ +{ + "resourceType" : "Observation", + "id" : "satO2", + "meta" : { + "profile" : [ + "http://hl7.org/fhir/StructureDefinition/vitalsigns" + ] + }, + "text" : { + "status" : "generated", + "div" : "

Generated Narrative with Details

id: satO2

meta:

identifier: o1223435-10

partOf: Procedure/ob

status: final

category: Vital Signs (Details : {http://terminology.hl7.org/CodeSystem/observation-category code 'vital-signs' = 'Vital Signs', given as 'Vital Signs'})

code: Oxygen saturation in Arterial blood (Details : {LOINC code '2708-6' = 'Oxygen saturation in Arterial blood', given as 'Oxygen saturation in Arterial blood'}; {LOINC code '59408-5' = 'Oxygen saturation in Arterial blood by Pulse oximetry', given as 'Oxygen saturation in Arterial blood by Pulse oximetry'}; {urn:iso:std:iso:11073:10101 code '150456' = '150456', given as 'MDC_PULS_OXIM_SAT_O2'})

subject: Patient/example

effective: 05/12/2014 9:30:10 AM

value: 95 % (Details: UCUM code % = '%')

interpretation: Normal (applies to non-numeric results) (Details : {http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation code 'N' = 'Normal', given as 'Normal'})

device: DeviceMetric/example

ReferenceRanges

-LowHigh
*90 % (Details: UCUM code % = '%')99 % (Details: UCUM code % = '%')
" + }, + "identifier" : [ + { + "system" : "http://goodcare.org/observation/id", + "value" : "o1223435-10" + } + ], + "partOf" : [ + { + "reference" : "Procedure/ob" + } + ], + "status" : "final", + "category" : [ + { + "coding" : [ + { + "system" : "http://terminology.hl7.org/CodeSystem/observation-category", + "code" : "vital-signs", + "display" : "Vital Signs" + } + ], + "text" : "Vital Signs" + } + ], + "code" : { + "coding" : [ + { + "system" : "http://loinc.org", + "code" : "2708-6", + "display" : "Oxygen saturation in Arterial blood" + }, + { + "system" : "http://loinc.org", + "code" : "59408-5", + "display" : "Oxygen saturation in Arterial blood by Pulse oximetry" + }, + { + "system" : "urn:iso:std:iso:11073:10101", + "code" : "150456", + "display" : "MDC_PULS_OXIM_SAT_O2" + } + ] + }, + "subject" : { + "reference" : "Patient/example" + }, + "effectiveDateTime" : "2014-12-05T09:30:10+01:00", + "valueQuantity" : { + "value" : 95, + "unit" : "%", + "system" : "http://unitsofmeasure.org", + "code" : "%" + }, + "interpretation" : [ + { + "coding" : [ + { + "system" : "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation", + "code" : "N", + "display" : "Normal" + } + ], + "text" : "Normal (applies to non-numeric results)" + } + ], + "device" : { + "reference" : "DeviceMetric/example" + }, + "referenceRange" : [ + { + "low" : { + "value" : 90, + "unit" : "%", + "system" : "http://unitsofmeasure.org", + "code" : "%" + }, + "high" : { + "value" : 99, + "unit" : "%", + "system" : "http://unitsofmeasure.org", + "code" : "%" + } + } + ] +} diff --git a/patient-generated-data-synthetic/src/test/resources/questionnaireResponse/3141.json b/patient-generated-data-synthetic/src/test/resources/questionnaire-response/3141.json similarity index 100% rename from patient-generated-data-synthetic/src/test/resources/questionnaireResponse/3141.json rename to patient-generated-data-synthetic/src/test/resources/questionnaire-response/3141.json diff --git a/patient-generated-data-synthetic/src/test/resources/questionnaireResponse/f201.json b/patient-generated-data-synthetic/src/test/resources/questionnaire-response/f201.json similarity index 100% rename from patient-generated-data-synthetic/src/test/resources/questionnaireResponse/f201.json rename to patient-generated-data-synthetic/src/test/resources/questionnaire-response/f201.json diff --git a/patient-generated-data/src/main/resources/db/changelog/db.changelog-master.yaml b/patient-generated-data/src/main/resources/db/changelog/db.changelog-master.yaml index 67a5fd6b..ca013915 100644 --- a/patient-generated-data/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/patient-generated-data/src/main/resources/db/changelog/db.changelog-master.yaml @@ -72,3 +72,28 @@ databaseChangeLog: type: int constraints: nullable: false + + - changeSet: + id: 5 + author: pteracuda + changes: + - createTable: + tableName: Observation + schemaName: app + columns: + - column: + name: id + type: varchar(32) + constraints: + primaryKey: true + nullable: false + - column: + name: payload + type: clob + constraints: + nullable: false + - column: + name: version + type: int + constraints: + nullable: false