I have been playing around with D3.js and C3.js to help visualize health data from FHIR. Today I will show you how to make a simple and interactive graph that charts the users Blood pressure leveraging C3.js and the SMART on FHIR api. You can find the code here on github The data is accessed using the SMART on FHIR api to retrieve all of the blood pressure observation results. The cool part is that you can dynamically explore the data by selecting the date range you want to view or select an individual data point to get more information of the observation. It doesn’t require any page refreshes and it is very seamless UI. You can potentially do a lot more such as toggle between different types of data such as show me BP for only standing up or show me BP taken by a provider. With this framework you can easily customize your graphs to your need.
SMART on FHIR
FHIR is a framework that tries to solve the healthcare interoperability problem by creating standardized data formats and making them available to use through Restful apis. The fundamental health care data component in FHIR is the resource. A resource is semi-structured data that can describe a patient's medical data. This can range from medications, observations and care plans. With this semi-structured data you now have access to granular clinical data for patients. SMART on FHIR is a framework developed by Boston Children’s Hospital or Harvard Medical School to help create apps using FHIR resources, oauth on top of existing EHRs in order to make healthcare more connected.
D3.js and C3.js
Retriving data from your FHIR API
Now how do you create graphs using the SMART api? The easiest way to think about it is that just with any graph you have variables that contain specific data points. In D3 you can define your data in an array. Each data point can be an object that has the x,y variable but it can also have anything else such as description, code type or units. So you can have a BP measurement of 123mmhg taken on 1/5/2016 and the description is systolic pressure. You can retrieve this information from your FHIR data schema and store it all together in a nested array. For example it may look like [[bp: date: 110,1/5/2016],[bp: 120,date: 1/7/2016]] now with this information you are able to display it any way you chose using D3. All you need to do is read the data from FHIR and store it in a specific data structure so that D3 can use it. D3 library uses helper functions that help you create generic elements such as a line graph I will walk you through how to create a basic graph with D3js and using data from FHIR.
We are going to create the 3 buttons that will generate a different graph based on which patient is selected. You will call the fhir client and connect to the smart test server for a specific patient by using the service url and the patient's id. In this example we will have 3 patients so we can see each of their bp data. Each button when clicked will execute the id function with the patient's unique id as the parameter passed through it. This is done by using a jquery function when clicking each of the buttons. That id is used to connect to the smart server and retrieve their data and generate the graph. Granted this value would never be hard coded in production it just makes it easier to test. You will store the patient id and later on have access to retrieve specific data determined by the resources you chose to search for.
Next we will create the title of our graph displaying the patient's name that is selected. The FHIR read function can be applied to the patient profile object to retrieve their name. This profile resource has access to the patients name emergency contacts and other basic information. In this example we are retrieving the patients given first name and their family name. We will combine their first name and their family name to create their full name which we will store in the formatted varible. We will call this function later in our c3.js code in the title section of our graph. It will make a lot more sense once you look at how the data is structured for the name attribute.
Retriving The Patient's Blood Pressure Data
The first part of the code is to use pt.api.search this is a smart function that allows you to search a resources type, furthermore you can query a particular resource by a filter such as the code value to only retrieve relevant information. In this case 55284-4 are the lonic code values for a blood pressure observations which will include systolic and diastolic measurements. Now that our query of all the blood pressure readings for this patient is saved in the bps variable we will loop over each entry and retrieve each encounter where blood pressure was taken. Bp.resource.component will store the individual resource observation in the variable blood. We will then store the date the blood pressure observation was taken on in our x array. This will be the array will store all our dates of the observations and help build our x axis. Within each bp observation there is a systolic and diastolic entry. We will store the diastolic and systolic values within their own arrays so we can create two line graphs. For a single bp observation we will loop over the components and if it has a 8480-6 lonic code we will store the b.valueQuantity.value in our systolic array. The same goes for our diastolic lonic code 8462-4.
Graphing Our Data Using C3.js
We will create the chart by using a c3.js function .generate. This will create a graph and encapsulate all of its components. As we said before our title will display the current patient's name. We will call the name() function and the return the patient's name and then concatenate it with "Blood Pressure Data". So you can see when you click on the different buttons the name on the title changes. Then we declare our x and y variables. In this case we will have 2 y variables that will generate two line graphs one for systolic pressure and one for diastolic pressure. We will call our diastolic and systolic arrays that we created when we queried our blood pressure observations. The x variable will be the dates when each of the observations were taken. C3.js makes it easy to create a brushing which is a miniaturized version of the graph that you can interact with and select a specific range of x values you want to display on your main graph All you need to do in C3.js to enable this is call subchart true.
Formatting our Axis
Let's now customize our x and y axis. Our x axis will be when we took our blood pressure measurement. To make our chart less busy we will set the amount of tick marks to just 6. Additionally, we change the format of the date to just display month date and year. If we don’t format the date the label will also include the time which makes the graph hard to read. The y axis label our blood pressure readings in mmHg . The y axis will dynamically change based on the y domain for the data set.
Creating A Tool Tip
The tool tip will allow you to click on a data point display the time the blood pressure was taken and both the systolic and diastolic measurement. The title of our tooltip will be the date the measurement was taken. We create a function in line 42 to convert our time into a simple format so it can fit in our tool tip. Lastly we return the Y value of our data point which will be the systolic and diastolic measurement. Try it yourself and click on a point and see what is displayed.
This was a basic introduction on how to use the FHIR api to graph a patient's data using C3.js. This is really the first iteration of the graph and there is room for a lot of improvement. I wish I had a better ability to create test patients and create test data so I can create applications that can combine various data resources. Such as seeing how blood pressure changes when a certain drug is being taken by a patient. I can make this an ongoing project with added improvements. Here are some of my thoughts.
- I want to be able to create better UI for mobile
- Enable real time graphing
- Calculate and graph mean BP
- Show contextual data such as drug usage so I can see the effects on BP