FHIR Chat · using smart-on-fhir/client-py to post data to HAPI FHIR · python

Stream: python

Topic: using smart-on-fhir/client-py to post data to HAPI FHIR


view this post on Zulip Matt Antalek (Dec 09 2020 at 20:03):

Hi All,

I'm learning how to use FHIR and I came across the smart-on-fhir client library. I would like to know if there are any tutorials on how to post data to a FHIR server. For example, what I would like to do is create a new patient on the FHIR server and then add a PDF file associated with that patient. I'm using a local docker container running this image.

Any suggestions much appreciated. I've had some success doing basic operations but I'm struggling to understand more complex tasks and how the FHIR resources are related to each other and used - like uploading the PDF described above.

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:08):

What is the PDF association with the patient? That is where FHIR starts: with defining what information is. Is this a "additional information about the patient"? or is this a discharge letter? Or a patient signed consent?... All those things have different places in FHIR.

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:12):

But generally the process would be:

  1. If that information is intrinsic part of the "Patient" object, then you can create an extension on the patient. If it's something else, you can surely find another FHIR resource that has a similar intent.
  2. Whether as an extension or part of a resource, the PDF would be base-64 encoded and submitted as a Binary resource, or in an Attachment data type (for examlpe in DocumentReference resource)

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:13):

Then you POST the patient, with the encoded PDF as an extension , or you POST the PDF later as part of the other resource

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:13):

(is this helpful)?

view this post on Zulip Matt Antalek (Dec 09 2020 at 21:20):

Hi @Jose Costa Teixeira - thanks! Yes, it's helpful.

For what I'm working on, this PDF would be a clinic note, so something that I wouldn't consider to be part of the patient object directly, but should be associated to it. Here is a bit of example code for what I'm trying to do where I create a DocumentReference object to hold the PDF data:

from fhirclient.models.attachment import Attachment
from fhirclient.models.binary import Binary
from fhirclient import client
import base64

# client to local HAPI FHIR server
smart = client.FHIRClient({'api_base':'http://localhost:8080/baseDtsu3', 'app_id':''})

smart.prepare()

# get a patient
patient = Patient.read('1', smart.server)

# make a document reference
dr = DocumentReference()
dr.subject = patient

# make attachment
a = Attachment()
a.contentType = 'application/pdf'
# read in pdf file
pdf_file = ....
pdf_data = None
with open(pdf_file, 'rb') as f:
  pdf_data = f.read()
  pdf_64 = base64.b64encode(pdf_data)
  pdf_64m = pdf_64.decode('utf-8')

a.data = pdf_64m
dr.attachment = a
dr.create(smart.server)

Where I'm getting hung up is that the dr.subject = patient throws an error, saying the object should be a FHIRReference object. However in the documentation I haven't been able to find the proper method of creating these references to each other. Example code in other languages (like Java) seems to be a bit more straightforward. There may be other python libraries that are easier to use, but this was one of the first I came across. Any suggestions appreciated.

view this post on Zulip Matt Antalek (Dec 09 2020 at 21:22):

Also of note - tried setting the attachment as a Binary object, but that threw an error in the attachment stating that the Attachment.data attribute should be a python string.

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:42):

http://build.fhir.org/references.html#Reference

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:43):

Reference is a data type, not a pointer to an object

view this post on Zulip Jose Costa Teixeira (Dec 09 2020 at 21:45):

dr.subject.reference= <URL of your patient>)
where the url of the patient is [server]/Patient/<your patient.id>

view this post on Zulip Matt Antalek (Dec 10 2020 at 17:25):

@Jose Costa Teixeira - have you used the smart-on-fhir/client-py library before? Is there a way I can easily find the url for the patient object after I've read the object from the server?

view this post on Zulip Jose Costa Teixeira (Dec 10 2020 at 17:26):

I haven't used the Library so I don't know if there is a short way to get that.

view this post on Zulip Eric Haas (Dec 10 2020 at 19:33):

have you used the smart-on-fhir/client-py library before? Is there a way I can easily find the url for the patient object after I've read the object from the server?

I don't understand your question, how can you read a patient without knowing its URL

here is what I do using the requests library....

view this post on Zulip Eric Haas (Dec 10 2020 at 19:44):

Get patient and use client_py model

from requests import get
from json import loads, dumps
from fhirclient.r4models import patient as P

some global variables...

base = 'http://test.fhir.org/r4'
#base = 'http://hapi.fhir.org/baseR4'
#base = 'http://wildfhir4.aegis.net/fhir4-0-1'

headers = {
        'Accept':'application/fhir+json',
        'Content-Type':'application/fhir+json'
        }

p_id  = ''

Read Patient using requests package

def get_patients():

    r = get(f'{base}/Patient', headers = headers)
    #print(r.json()['entry'])
    try:
        ids = [i['resource']['id'] for i in r.json()['entry'] if i['resource']['resourceType']=='Patient']
    except Exception as e:
        pass
        #print(f'Error: {e}')
    else:
        print(ids)
    return ids[0]


def get_patient(p_id):

    r = get(f'{base}/Patient/{p_id}', headers = headers)

    try:
        pyfhir_patient = P.Patient(r.json())
    except Exception as e:
        pass
        #print(f'Error: {e}')
    else:
        print(pyfhir_patient)
        print(f'pyfhir_patient.id = {pyfhir_patient.id}')
        print(f'pyfhir_patient.name.family.given = {pyfhir_patient.name[0].given[0]}')
        print(f'pyfhir_patient.name.family = {pyfhir_patient.name[0].family}')

p_id = get_patients()
get_patient(p_id)
['0b327bc5-13e5-4510-8a17-91bc0bf081', '0ecdf6ab-a506-4c44-8b70-b413274c4e', '1', '20217344', '20217345', '20217346', '20217347', '20217348', '20217349', '20217351', '20217352', '20217353', '20217354', '20217355', '20217356', '20217357', '20217358', '20217359', '20217360', '20217361', '20217362', '20217363', '20217364', '20217365', '20217366', '20217367', '20217368', '20217369', '20217382', '20217383', '20217395', '20217412', '20217416', '20217417', '20217419', '20217425', '20217433', '20217435', '20217437', '20217438', '20217439', '20217440', '20217441', '20217442', '20217468', '20217501', '20217530', '20217531', '20217532', '20217533']
<fhirclient.r4models.patient.Patient object at 0x1031a74e0>
pyfhir_patient.id = 0b327bc5-13e5-4510-8a17-91bc0bf081
pyfhir_patient.name.family.given = Jason
pyfhir_patient.name.family = Lee

view this post on Zulip Matt Antalek (Dec 11 2020 at 14:05):

@Eric Haas so the client-py library has some built in methods that allow you to query the patient object without explicitly typing the url. for example:

from fhirclient.client import FHIRClient
from fhirclient.models.patient import Patient

smart = FHIRClient({'api_base':'http://localhost:8080/baseDtsu3', 'app_id':''})
smart.prepare()

p = Patient.read("<id-of-patient>", smart.server)

So, you could get the url of p by combining the strings of p.relativePath() and p.server.base_uri but its a bit clunky. I didnt know if there was an object somewhere in the library that implemented some convenience methods.

view this post on Zulip Eric Haas (Dec 11 2020 at 20:13):

Yes I never used any of those methods, stuck to requests

view this post on Zulip Pascal Pfiffner (Dec 16 2020 at 15:27):

Man @Eric Haas , those methods use requests underneath. ;)

view this post on Zulip Eric Haas (Dec 16 2020 at 17:19):

I knew that, I never bothered to use them since I was used to using requests directly


Last updated: Apr 12 2022 at 19:14 UTC