Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Tutorial: plot a patient’s blood pressure

In this tutorial we will connect to the Berkeley Demo JupyterHealth Exchange, find a patient in a study, fetch their blood pressure readings, and plot them over time.

By the end you will have a chart of one patient’s blood pressure, and a count of how many of their readings were normal, elevated, or in the hypertension range.

You don’t need to install anything: everything runs on the Berkeley Demo JupyterHealth Hub.

Open this tutorial on the Demo JupyterHealth Hub

Before you start

You need an account on the Berkeley Demo JupyterHealth Exchange and to be logged into the Berkeley Demo JupyterHealth Hub. If you don’t have an account yet, follow Sign up for the Exchange.

  1. Click the launch button above. The Hub copies this notebook into your home directory and opens it in JupyterLab.

  2. In JupyterLab, run each code cell in order by clicking into it and pressing Shift + Enter.

After each step, compare what you see with the text under You should see.

Step 1: Connect to the JupyterHealth Exchange

The JupyterHealth Exchange stores the health data. We talk to it through a Python library called jupyterhealth_client. The Hub has already logged you in, so we only need to create a client.

Run the cell below.

You should see one line starting with Connected as, followed by your name and email in parentheses.

Every request we make from now on goes through client.

Step 2: Find a study

Data in the Exchange is organized into studies. You can only see the studies your organization runs.

Run the cell below to list them.

You should see a list of studies. The number in square brackets is the study’s ID.

We will use the study with ID 30001. If you don’t see it in your list, change the number below to the ID of one of your studies.

Run the cell.

Step 3: Find a patient

Now let’s list the patients in that study.

You should see a list of patients, each with their ID in square brackets.

We will use the patient with ID 40028. If they’re not in your list, copy any ID from the list into the cell below instead.

Run the cell.

Step 4: Fetch the blood pressure readings

Next we ask the Exchange for this patient’s blood pressure readings in this study. The client returns them as a pandas DataFrame: a table with one row per reading.

Run the cell below.

You should see Found ... readings, then the first five rows of a wide table. This is the raw data, exactly as the Exchange stores it. We only need the time and the two measurements.

If you see Found 0 readings, go back to Step 3 and pick a different patient.

What are all these columns?

Each row is one reading, stored in the Open mHealth format. pandas hides some of the middle columns behind ... to save space. The columns fall into a few groups:

  • About the record: id, status, resource_type, code and the meta_... columns say what kind of data this is and when it was stored in the Exchange.

  • When it was measured: effective_time_frame_date_time is in UTC, and effective_time_frame_date_time_local is in the patient’s local time.

  • The measurement: systolic_blood_pressure_value and diastolic_blood_pressure_value, with their units (mmHg) in the matching ..._unit columns.

  • Extra details, such as the external_datasheets_... columns. NaN means a field is empty for that reading.

Let’s keep just those three columns, and give them short names.

You should see a table with three columns: time, systolic and diastolic.

Step 5: Plot blood pressure over time

Now for the chart. Run the cell below.

You should see a chart with two lines, systolic on top and diastolic below, with the gap between them shaded.

Notice how much the readings move around from one day to the next. To make sense of them, it helps to group them, which we’ll do next.

Step 6: Group readings into categories

We’ll label each reading using the American Heart Association categories:

  • normal: systolic below 120 and diastolic below 80

  • elevated: systolic 120–129 and diastolic below 80

  • hypertension: systolic 130 or higher, or diastolic 80 or higher

Note: The AHA splits hypertension into stage 1 (130–139 / 80–89) and stage 2 (140 / 90 or higher). Many other guidelines, including the European ones, only call it hypertension from 140 / 90. We use three categories to keep things simple. A single reading in the hypertension range doesn’t mean someone has hypertension: a diagnosis is based on the average of many readings.

Run the cell below to label each reading and count how often each category occurs.

You should see each category with the percentage of readings that fall into it. The percentages add up to 100.

Step 7: Highlight readings out of range

Finally, let’s draw the chart from Step 5 again, this time coloring each reading by its category.

You should see the same chart as in Step 5, with dots in green (normal), amber (elevated) and red (hypertension). Both dots of a reading share its color, so a red systolic dot can sit next to a diastolic dot that is in range, or the other way round.

What you’ve done

In this tutorial you:

  1. connected to the JupyterHealth Exchange with JupyterHealthClient

  2. listed your studies and the patients in a study

  3. fetched a patient’s blood pressure readings as a table

  4. plotted them over time

  5. grouped them into clinical categories and highlighted them on the chart

Try going back to Step 3, picking a different patient, and running the cells again.

Next steps