Using client-py, this project aims to provide some simple demos to help people get started with the python client.
This is also a learning excercise - so if you see anything that could be done better, please let us know.
Getting started
Note: This project pip install
s the latest client-py code. We could install this commit if breaking changes are introduced.
We're using the latest client-py code becuase PyPI history shows the last available release was 3.2.0
2018-02-06 ... and we want to use some of the new FHIR R4 features.
If you want to run everything on your own machine
Clone this project and set-up a conda environment
git clone https://github.com/pete88b/smart-on-fhir-client-py-demo.git
cd smart-on-fhir-client-py-demo
conda create -n smart-on-fhir-client-py-demo python==3.8 -y
conda activate smart-on-fhir-client-py-demo
pip install -r requirements.txt
nbdev_install_git_hooks
Start jupyter
If you have already created and activated your conda environment, you can start a notebook server with;
jupyter notebook
If you want to run demo notebooks using google colab
- Open this notebook in colab
- Open _flask_hello_world_colab.ipynb in colab
- Open 51_flask_client_py_readme.ipynb in colab
The cell below will install the fhirclient if you're running in colab.
Define print_resource
- a generic way to print a resource
We use print_resource(procedure)
etc, rather than looking at specific resource details with code like procedure.code.coding[0].as_json()
, so that the demos won't fail if resouces are missing specific content.
def print_resource(resource, indent=None, length=100):
s=json.dumps(resource.as_json(), indent=indent)
print(s[:length-4]+' ...' if len(s)>length else s)
Lets start by trying to make something like the code examples in client-py README.md work.
These docs refer to the FHIR server https://fhir-open-api-dstu2.smarthealthit.org which is probably not running any more.
The following demos will use http://wildfhir4.aegis.net/fhir4-0-0 - which is one of the "open" servers listed on the public test servers wiki. If you'd like to try other servers, feel free to change api_base
↓
settings = {
'app_id': 'my_web_app',
'api_base': 'http://wildfhir4.aegis.net/fhir4-0-0'
}
Read Data from Server
Note: We use Resource ID
'f001'
rather than 'hca-pat-1'
- which could be found with a Aegis FHIR4-0-0 GUI search.
If the p.Patient.read
call raises FHIRNotFoundException: <Response [404]>
, it probably means that the Resource ID
does not exist on the server.
from fhirclient import client
smart = client.FHIRClient(settings=settings)
import fhirclient.models.patient as p
patient = p.Patient.read('f001', smart.server)
print('Birth Date', patient.birthDate.isostring)
print('Patient Name', smart.human_name(patient.name[0]))
Note: We could show the full patient resource as JSON with patient.as_json()
- which should give us the same data as GET
http://wildfhir4.aegis.net/fhir4-0-0/Patient/f001
from fhirclient import server
smart = server.FHIRServer(None, settings['api_base'])
import fhirclient.models.patient as p
patient = p.Patient.read('f001', smart)
patient.name[0].given
Search Records on Server
Note: I think GET
http://wildfhir4.aegis.net/fhir4-0-0/Patient/f001/Procedure should work
smart = client.FHIRClient(settings=settings)
import fhirclient.models.procedure as p
search = p.Procedure.where(struct={'subject': 'f001', 'status': 'completed'})
procedures = search.perform_resources(smart.server)
for procedure in procedures:
print_resource(procedure)
# print(procedure.id, procedure.code.coding[0].as_json())
To include the resources referred to by the procedure via subject
in the results
Before calling search.include('subject')
, search.construct()
gave us
Procedure?subject=f001&status=completed
After calling search.include('subject')
, search.construct()
gave us
Procedure?subject=f001&status=completed&_include=Procedure:subject
so ... search.perform_resources
will now give us a list of procedures and patients that the procedures refer to.
search = search.include('subject')
procedures = search.perform_resources(smart.server)
for resource in procedures:
print(resource.__class__.__name__)
print_resource(resource)
we could check the type of resource and run specific code for each type with something like
for resource in procedures:
if isinstance(resource, p.Procedure):
# process Procedure here
print(resource.id, resource.code.coding[0].as_json())
else:
# process Patient here
print('Patient', resource.id)
import fhirclient.models.medicationadministration as m
search = search.include('partOf', m.MedicationAdministration, reverse=True)
procedures = search.perform_resources(smart.server)
for resource in procedures:
print(resource.__class__.__name__)
print_resource(resource)
to get the raw Bundle instead of resources only, you can use:
bundle = search.perform(smart.server)
# we'll just show the 1st 200 characters of the bundle (after converting to JSON)
print_resource(bundle, indent=2, length=200)
import fhirclient.models.patient as p
import fhirclient.models.humanname as hn
patient = p.Patient({'id': 'patient-1'})
print(patient.as_json()) # prints `patient-1`
name = hn.HumanName()
name.given = ['Peter']
name.family = 'Parker'
patient.name = [name]
print(patient.as_json()) # prints patient's JSON representation, now with id and name
name.given = 'Peter'
try:
patient.as_json()
except Exception as ex:
print('patient.as_json() raised', type(ex),'with message')
print(ex)
data_path=Path('data')
data_path.mkdir(exist_ok=True)
Create a file by reading a patient from the server and writing as json
import fhirclient.models.patient as p
smart = client.FHIRClient(settings=settings)
patient = p.Patient.read('f001', smart.server)
with open(data_path/'patient.json', 'w') as f:
f.write(json.dumps(patient.as_json(), indent=2))
Now we can read the json file and initialize a Patient
with open(data_path/'patient.json', 'r') as h:
pjs = json.load(h)
patient = p.Patient(pjs)
patient.name[0].given
Run the flask app
51_flask_client_py_readme.ipynb creates a Flask app like the client-py demo flask app.
You can run python smart_on_fhir_client_py_demo/flask_client_py_readme.py
from the command line and hit
This is a little different to the client-py demo;
- It's set-up to run against http://wildfhir4.aegis.net/fhir4-0-0 which is a no-auth server
- It'll allow you to select a patient if you're running against a no-auth server
- It'll allow you to pass a patient ID as a URL paramter
- Note: It hasn't been tested with an auth server yet.