-
Notifications
You must be signed in to change notification settings - Fork 646
Physiology Models
Synthea supports the ability to run physiology models, using granular partial differential equations, in addition to the statistical markov chains used in most modules. These physiology models can be initiated in two ways:
- running a one-off simulation on a single patient.
- adjusting the
synthea.properties
file and including the physiology data in the entire patient cohort.
Either approach allows the user to adjust the differential equation solver, step size, sim duration, and configuration for output charts if desired. Output files will be in the output/physiology
directory.
You will need to set the following two fields to true
in the src/main/resources/synthea.properties
file.
# Use physiology simulations to generate some VitalSigns
physiology.generators.enabled = true
# Allow physiology module states to be executed
# If false, all Physiology state objects will immediately redirect to the state defined in
# the alt_direct_transition field
physiology.state.enabled = true
Run any single physiology simulation with one of the following commands. This is useful for optimizing and debugging the physiology model to your needs, before adding it into the large population cohort.
./gradlew physiology --args="config/simulations/circadian_clock.yml"
./gradlew physiology --args="config/simulations/ecg.yml"
./gradlew physiology --args="config/simulations/insulin_signalling_diabetic.yml"
./gradlew physiology --args="config/simulations/insulin_signalling_normal.yml"
./gradlew physiology --args="config/simulations/liver_metabolism.yml"
./gradlew physiology --args="config/simulations/mammalian_circadian_rhythm_non_24hr.yml"
./gradlew physiology --args="config/simulations/menstrual_cycle.yml"
./gradlew physiology --args="config/simulations/o2_transport_metabolism.yml"
./gradlew physiology --args="config/simulations/plasma_melatonin.yml"
./gradlew physiology --args="config/simulations/pulmonary_fluid_dynamics.yml"
./gradlew physiology --args="config/simulations/pulmonary_oxygen_intake.yml"
./gradlew physiology --args="config/simulations/telomere_associated_dna_damage.yml"
./gradlew physiology --args="config/simulations/weight_change.yml"
Graphs and raw data in CVS files will be found in output/physiology
folder.
You may also wish to create a large population of 10,000 or more individuals, and search for gallblader patients (which are currently the only patients that have ECG physiology data attached to them.)
Alternatively, you can run physiology models on the entire patient cohort. Be forewarned! This can be computationally expensive, and may slow the run down considerably.
# generate the sample patients
./run_synthea -p 100
You can find the original documentation for the biomodels at the following links:
- Smith2004_CVS_human
- Guyton1972_PulmonaryOxygenIntake
- Guyton1972_PulmonaryFluidDynamics
- Lai2007_O2_Transport_Metabolism
- Brännmark2013 - Insulin signalling in human adipocytes (normal condition)
- Brännmark2013 - Insulin signalling in human adipocytes (diabetic condition)
- Talemi2015 - Persistent telomere-associated DNA damage foci (TAF)
- ChowHall2008 Dynamics of Human Weight Change_ODE_1
- Hong2009_CircadianClock
- Brown1997 - Plasma Melatonin Levels
- Leloup2004 - Mammalian Circadian Rhythm models for 23.8 and 24.2 hours
- Roblitz2013 - Menstrual Cycle following GnRH analogue administration
- Kyrylov2005_HPAaxis
- Jerby2010_Liver_Metabolism
Each of the new physiology models is managed by a generator function, which handles inputs and outputs into the set of partial differential equations contained within the model. Example input and outputs looks like the following:
inputs:
# # Effects of age and BMI loosely estimated from a comprehensive study on adult blood pressure
# # percentiles (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4553889/)
# # More research is needed to determine appropriate age / BMI effects on all model parameters.
- fromExp: "1.1889 + 0.025 * (#{BMI} - 21.7) + (if #b{blood_pressure_controlled} then 0 else (0.0112 * #{age}))"
to: R_sys
variance: 0.25 # Allowable variance in input to avoid running simulation
outputs:
- fromExp: "((Max(#{V_lv}) - Min(#{V_lv})) / Max(#{V_lv}))*100"
to: Left ventricular Ejection fraction
Users of Synthea who wish to customize and optimize these physiology models to their use cases are encouraged to look at the fromExp
field, which contains a mapping function that can be optimized for particular use cases. In particular, we note the following functionalities that users should be aware of:
- It is possible to pull in variables from the patient medical chart, using the
#{foo}
syntax. - Basic
if then else
functionality is supported within the expressions. - Functions are supported within the equations, as demonstrated by the
Max() and Min()
functions. - The functions map between parameters in the partial differential equations and variables in the patient record via the
to
field.
With this syntax and grammar, motivated users can optimize these physiology functions to produce daily activity patterns that the simulated patients follow, such as taking medications each day, exercising, or other behaviors. Seasonal trends can be developed. Acute response to emergencies and accidents can be modeled. And so forth.
It's important to understand that the physiology models produce continuous theoretical data for the patient over a discrete time period. This data is not
the kind of data that would be generated by any particular medical device or wearable; rather, these models describe a theoretical representation of the biological functions going on within a person; of which a medical device or wearable will take a discrete snapshot at any particular time.
To put it in calculus terms, these models represent continuous functions; and any particular clinical observation will be a derivative function at a specific moment in time.
To visualize this, imaging the circadian cycle; which is roughly timed with the human sleep/wake cycle. Physiologically, this cycle is generally measured by melatonin and cortisol levels, which are increasing and decreasing throughout the day.
At certain thresholds, these melatonin and cortisol levels impact a person's natural sleep cycle, in both the time of day they go to sleep, and the length of sleep. We can represent that with an intersecting function, like so.
And what we're seeking with these optimized functions, is to take our continuous theoretical function, and filter it, such that it produces the same data that we might obtain from an empirical clinical measurement. So, for instance, wearing an iWatch with a sleep tracking app, might generate the following data:
Another use case for these intersecting functions, is that of setting sensitivity thresholds. Consider the case of an ECG monitor. In the following 10s example, we have an intersecting function that produces a count of N=7 beats per 10s, which could then be mapped to a FHIR Observation for a single vital signs measurement.
Alternatively, if we adjusting the threshold of our intersecting function, we could create a more permissive filter, with a count of N=11.
Such thresholding allows us to use the physiology models in increasingly complex ways. We may take the same model, and use it to generate physiology data:
Or, we might focus on a different part of the continuous function, and use the intersecting function to generate behavioral or mood data instead.
Similar, depending on thresholding levels, one might use a pulmonary oxygen intake model to model chest breathing vs diaphragmatic breathing.
How these functions are used to represent discrete data generated by medical devices and wearables is left to the reader. Suffice it to say that you'll want something like the following:
# Melatonin levels indicating sleep levels
outputs:
- fromExp: "if (#{melatonin} > 1.4) then 50 else 80"
to: heartrate
Or better yet, perhaps the following
# Melatonin levels indicating sleep levels
outputs:
- fromExp: "if (#{melatonin} > 1.4) then 50 else null"
to: heartrate
Get creative. Between if/then
statements, functions, and input/output mapping, there's enough flexibility to get creative and use these physiology models to create all sorts of example wearables data.