omoponfhir / omoponfhir-main

Main OMOPonFHIR Settings
Apache License 2.0
45 stars 15 forks source link

Basic Setup Help #3

Open psbrandt opened 4 years ago

psbrandt commented 4 years ago

Hi,

I've been trying to get the latest master set up on my test database, but haven't had much luck unfortunately. So, I decided to try and get things running using your test database instead. I've created the following Compose file that sets up OMOP on FHIR using the Docker files you provide:

# docker-compose.yml
version: "3"
services:
  omoponfhir-main:
    build:
      context: https://github.com/omoponfhir/omoponfhir-main.git#3be4f61674b5b62bffcf7b3a10c725ad20190f41
    restart: unless-stopped
    ports:
      - "9090:8080"
    environment: # importantly specify the correct schema
      - JDBC_URL=jdbc:postgresql://omopv5fhir-pgsql:5432/postgres?currentSchema=omop_v5
      - JDBC_USERNAME=postgres
      - JDBC_PASSWORD=i3lworks
    networks:
      omoponfhir:
  omopv5fhir-pgsql:
    build:
      context: https://github.com/omoponfhir/omopv5fhir-pgsql.git#0f21fcf5fb359b14f725d968b937d77a5a048117
    restart: unless-stopped
    ports:
      - "6543:5432"
    networks:
      omoponfhir:
networks:
  omoponfhir:

To recreate my setup, copy the above into a docker-compose.yml file, then run:

docker-compose up omopv5fhir-pgsql

Once the data is loaded, hit Ctrl+C and run:

docker-compose up

In my case, at this point it seems like the WAR file is deployed, and the application started up without errors. My question, for now, is how do I actually retrieve the resources? I did manage to dig up the Basic Authentication credentials here, but I can't seem to actually find any resources. Here are some examples of what I've tried:

Search For Patient by Name

curl  -H 'Authorization: Basic Y2xpZW50X29tb3A6c2VjcmV0' 'http://localhost:9090/omoponfhir-stu3/fhir/Patient?name=Solo'
{
  "resourceType": "Bundle",
  "id": "83a50675-0a10-452b-bfe5-ed812a149f63",
  "meta": {
    "lastUpdated": "2019-12-31T04:03:22.411+00:00"
  },
  "type": "searchset",
  "total": 0,
  "link": [
    {
      "relation": "self",
      "url": "http://localhost:9090/omoponfhir-stu3/fhir/Patient?name=Solo"
    }
  ]
}

Find Patient by CDM ID

curl  -H 'Authorization: Basic Y2xpZW50X29tb3A6c2VjcmV0' 'http://localhost:9090/omoponfhir-stu3/fhir/Patient/1'
{
  "resourceType": "OperationOutcome",
  "text": {
    "status": "generated",
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h1>Operation Outcome</h1><table border=\"0\"><tr><td style=\"font-weight: bold;\">ERROR</td><td>[]</td><td><pre>Resource Patient/1 is not known</pre></td>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</table>\n\t</div>"
  },
  "issue": [
    {
      "severity": "error",
      "code": "processing",
      "diagnostics": "Resource Patient/1 is not known"
    }
  ]
}

Search for Condition by Code

curl  -H 'Authorization: Basic Y2xpZW50X29tb3A6c2VjcmV0' 'http://localhost:9090/omoponfhir-stu3/fhir/Condition?code=428'
{
  "resourceType": "Bundle",
  "id": "1a376385-e281-4aed-a075-c151b246bd42",
  "meta": {
    "lastUpdated": "2019-12-31T04:15:44.877+00:00"
  },
  "type": "searchset",
  "total": 0,
  "link": [
    {
      "relation": "self",
      "url": "http://localhost:9090/omoponfhir-stu3/fhir/Condition?code=428"
    }
  ]
}

Any help or a perhaps a pointer to the appropriate documentation would be greatly appreciated.

psbrandt commented 4 years ago

I guess I can add another data point, which is that I'm seeing the following warning on the tester at http://localhost:9090/omoponfhir-stu3/tester/home:

Warning! Failed to load conformance statement, error was: ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException: Failed to parse response from server when performing GET to URL http://localhost:9090/omoponfhir-stu3/fhir/metadata - org.apache.http.conn.HttpHostConnectException: Connect to localhost:9090 [localhost/127.0.0.1] failed: Connection refused (Connection refused)

The java exception I see in the logs is:

ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException: Failed to parse response from server when performing GET to URL http://localhost:9090/omoponfhir-stu3/fhir/metadata - org.apache.http.conn.HttpHostConnectException: Connect to localhost:9090 [localhost/127.0.0.1] failed: Connection refused (Connection refused)

However, sending a GET request directly to http://localhost:9090/omoponfhir-stu3/fhir/metadata seems to correctly return the CapabilityStatement. My guess is that this is because there is nothing running on port 9090 of the omoponfhir-main container, and it's getting that port via the context path on the request.

This isn't a big deal for me though, since I'm more interested in getting access to my data programmatically than using the tester.

myungchoi commented 4 years ago

Please try GET to http://localhost:9090/omoponfhir-stu3/fhir/Patient

This should return entire list of patients. If this returns empty, then the database does not have all the data we need. If you loaded your own data, please note that you will also need to populate f_person table with names. f_person table has one-to-one relationship with person table.

psbrandt commented 4 years ago

As shown, I am using your provided database. Here is the result of trying to get the list of patients:

curl  -H 'Authorization: Basic Y2xpZW50X29tb3A6c2VjcmV0' 'http://localhost:9090/omoponfhir-stu3/fhir/Patient'
{
  "resourceType": "Bundle",
  "id": "2bf43cfd-3315-420a-a47e-ed9ee43bc80d",
  "meta": {
    "lastUpdated": "2019-12-31T14:35:39.880+00:00"
  },
  "type": "searchset",
  "total": 0,
  "link": [
    {
      "relation": "self",
      "url": "http://localhost:9090/omoponfhir-stu3/fhir/Patient"
    }
  ]
}

It looks like empty CDM tables were created in the public schema. How do I configure OMOP on FHIR to use the omop_v5 schema that exists in the omopv5fhir-pgsql database?

psbrandt commented 4 years ago

I was able to configure the schema in the connection string by adding ?currentSchema=omop_v5. I updated the the docker-compose.yml above for those who might find this issue later. Now I'm getting some patients:

curl  -H 'Authorization: Basic Y2xpZW50X29tb3A6c2VjcmV0' 'http://localhost:9090/omoponfhir-stu3/fhir/Patient?name=Kirk'
{
  "resourceType": "Bundle",
  "id": "272af23b-d3ee-4390-bc79-69eaeb726a5d",
  "meta": {
    "lastUpdated": "2019-12-31T17:34:41.620+00:00"
  },
  "type": "searchset",
  "total": 1,
  "link": [
    {
      "relation": "self",
      "url": "http://localhost:9090/omoponfhir-stu3/fhir/Patient?name=Kirk"
    }
  ],
  "entry": [
    {
      "fullUrl": "http://localhost:9090/omoponfhir-stu3/fhir/Patient/3",
      "resource": {
        "resourceType": "Patient",
        "id": "3",
        "meta": {
          "profile": [
            "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
          ]
        },
        "text": {
          "status": "generated",
          "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\">James <b>KIRK </b></div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>71263324</td></tr><tr><td>Date of birth</td><td><span>01 January 1980</span></td></tr></tbody></table></div>"
        },
        "identifier": [
          {
            "value": "71263324"
          }
        ],
        "active": true,
        "name": [
          {
            "family": "Kirk",
            "given": [
              "James"
            ]
          }
        ],
        "gender": "male",
        "birthDate": "1980-01-01"
      }
    }
  ]
}

Next Steps

You note the following:

If you loaded your own data, please note that you will also need to populate f_person table with names. f_person table has one-to-one relationship with person table.

Are there any additional setup steps I need to be aware of in order to get things up and running with my own data?

myungchoi commented 4 years ago

The testing postgresql is setup to use Postgres database with omop_v5 schema. Thus, you have to use currentSchema in the database URL. Glad to hear that you get it working.

If you want to use your own database, please make sure you get correct database url and credential for JDBC connection.

Now, there are two additional setup that needs to be done at the OMOP database. First, you will need to set up f_person table. And, populate the table with patient data. This needs to be 1-to-1 with person table. We have a SQL that does this for you. I need to ask the author if it's OK to publish here. If he does not allow, then you need to create the table. The SQL to create f_person table can also be obtained from the test database. You can change the owner to whatever you have in your database user space. It's

create table f_person ( person_id integer not null, family_name varchar(255), given1_name varchar(255), given2_name varchar(255), prefix_name varchar(255), suffix_name varchar(255), preferred_language varchar(255), ssn varchar(12), active smallint default 1, contact_point1 varchar(255), contact_point2 varchar(255), contact_point3 varchar(255), maritalstatus varchar(255) );

comment on table f_person is 'Extended one-to-one table with person table. This include person''s demographic information to support FHIR patient resource.';

alter table f_person owner to omop_v5;

create index f_person_person_id_idx on f_person (person_id);

Secondly, you need a view table, which combines measurement and observation tables as FHIR has only one resource (Observation) for both tables. This is UNION of two tables. Here is the SQL for the f_observation_view.

create view f_observation_view as SELECT measurement.measurement_id AS observation_id, measurement.person_id, measurement.measurement_concept_id AS observation_concept_id, measurement.measurement_date AS observation_date, measurement.measurement_time AS observation_time, measurement.measurement_type_concept_id AS observation_type_concept_id, measurement.operator_concept_id AS observation_operator_concept_id, measurement.value_as_number, NULL :: character varying AS value_as_string, measurement.value_as_concept_id, NULL :: integer AS qualifier_concept_id, measurement.unit_concept_id, measurement.range_low, measurement.range_high, measurement.provider_id, measurement.visit_occurrence_id, measurement.measurement_source_value AS source_value, measurement.measurement_source_concept_id AS source_concept_id, measurement.unit_source_value, measurement.value_source_value, NULL :: character varying AS qualifier_source_value FROM measurement UNION ALL SELECT (-observation.observation_id) AS observation_id, observation.person_id, observation.observation_concept_id, observation.observation_date, observation.observation_time, observation.observation_type_concept_id, NULL :: integer AS observation_operator_concept_id, observation.value_as_number, observation.value_as_string, observation.value_as_concept_id, observation.qualifier_concept_id, observation.unit_concept_id, NULL :: double precision AS range_low, NULL :: double precision AS range_high, observation.provider_id, observation.visit_occurrence_id, observation.observation_source_value AS source_value, observation.observation_source_concept_id AS source_concept_id, observation.unit_source_value, NULL :: character varying AS value_source_value, observation.qualifier_source_value FROM observation WHERE (NOT (observation.observation_concept_id IN (SELECT c.concept_id FROM concept c WHERE (((upper((c.concept_name) :: text) ~~ '%ALLERG%' :: text) OR (upper((c.concept_name) :: text) ~~ '%REACTION%' :: text)) AND (((c.domain_id) :: text = 'Observation' :: text) OR ((c.domain_id) :: text = 'Condition' :: text)) AND ((c.invalid_reason) :: text <> 'D' :: text)))));

alter table f_observation_view owner to omop_v5;

Hope this helps. And, if I get OK from f_person populating script, I will post it to this GitHub org.

psbrandt commented 4 years ago

Thanks, I will try to use the above statements to prepare my database.