Physiology Engine Interface

The following infomation is a method by method walk through of the PhysiologyEngine.h class that everything revolves around. Reading this in parrallel with the HowTo-EngineUse.cpp provided in the SDK will give you a firm understanding of using BioGears.

When you create an instance of a BioGears engine, you will be returned a pointer to a PhysiologyEngine object. This generic interface is the controlling class for a physiology engine modeling a single patient.

1 std::unique_ptr<PhysiologyEngine> bg = CreateBioGearsEngine("MyBioGearsEngine.log");

Logging

You can provide an optional string into this creation method that will create a log file on disk where the engine will output all errors, warnings and other logged information. It is highly recommended to create a log, and check it often. If you do not wish to have this engine create a log, you can pass in nullptr. You can also provide a callback class to the logger that will forward all logging events to so that your application can easily monitor the BioGears engine. For more details, please consult the HowTo-EngineUse.cpp file in the SDK. You can access and utilize this logger with in your own application as such:

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// Retrieve the Logger associated with this engine
4  //--------------------------------------------------------------------------------------------------
5  virtual Logger* GetLogger() = 0;

Initializing the Engine

There are two ways to initialize the engine once created.

Engine State

An engine state file is the exact state of the engine written into an xml file. Once loaded, the engine is instatly ready to process instructions. You can specify an xml file on disk, or a state object held in memory. You can optionally specify a specific simulation time for the engine to use as its initial simulation time. If no time is provided, the simulation time that is in the state file will be used. The SDK provides a state file for various patients at simulation time 0 located in the bin/states directory.

1 //--------------------------------------------------------------------------------------------------
2 /// \brief
3 /// Reset engine and set it to the state in the provided file.
4 /// You may provided a Simulation Time to be used if desired.
5 /// It will be reflected in the GetSimulationTime method.
6 /// Return value indicates engine was able to load provided state file.
7 /// Engine will be in a cleared state if this method fails.
8 //--------------------------------------------------------------------------------------------------
9 virtual bool LoadState(const std::string& file, const SEScalarTime* simTime=nullptr) = 0;
10 
11 //--------------------------------------------------------------------------------------------------
12 /// \brief
13 /// Reset engine and set it to the state in the provided file.
14 /// You may provided a Simulation Time to be used if desired.
15 /// It will be reflected in the GetSimulationTime method.
16 /// Return value indicates engine was able to load provided state file.
17 /// Engine will be in a cleared state if this method fails.
18 //--------------------------------------------------------------------------------------------------
19 virtual bool LoadState(const CDM::PhysiologyEngineStateData& state, const SEScalarTime* simTime = nullptr) = 0;

At any point during the life of an engine, you create your own state object for later use.

1 //--------------------------------------------------------------------------------------------------
2 /// \brief
3 /// Save the current state of the engine.
4 /// State will be written to a file if provided.
5 /// State object will be returned.
6 /// Engine will be in a cleared state if this method fails.
7 //--------------------------------------------------------------------------------------------------
8 virtual std::unique_ptr<CDM::PhysiologyEngineStateData> SaveState(const std::string& file = "") = 0;

Patient Creation

If you would like to create your own patient or apply a condition to a specific patient, you will need to initialize the engine with a patient definition.

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// locates the xml patient file and reads in the values.
4  ///
5  /// This will create an engine that you can send instructions (patient,actions,conditions) to dynamically.
6  /// The return value will indicate success failure of the creation of the engine.
7  /// Some combinations of patients and conditions may prevent the engine from stabilizing
8  ///
9  //--------------------------------------------------------------------------------------------------
10  virtual bool InitializeEngine(const std::string& patientFile, const std::vector<const SECondition*>* conditions = nullptr, const PhysiologyEngineConfiguration* config = nullptr) = 0;
11 
12  //--------------------------------------------------------------------------------------------------
13  /// \brief
14  ///
15  /// This will create an engine that you can send instructions (patient,actions,conditions) to dynamically.
16  /// The return value will indicate success failure of the creation of the engine.
17  /// Some combinations of patients and conditions may prevent the engine from stabilizing
18  ///
19  //--------------------------------------------------------------------------------------------------
20 virtual bool InitializeEngine(const SEPatient& patient, const std::vector<const SECondition*>* conditions = nullptr, const PhysiologyEngineConfiguration* config = nullptr) = 0;

When a patient definition is provided, BioGears will go through an initialization algorithm that will take several minutes as to tune the engine to model the specific state requested of the patient. This initalization method is also the only way to specify any conditions (chronic/disease states).

Patient Conditions

Environment Conditions


Initializing the patient simulation with conditions will extend the initialization time by a few more minutes. Once the InitalizeEngine method returns, the engine is stabilize, and it is recommended to save the engine state for future use. (Assuming the patient vitals are acceptable, it may take some adjusting of condition severity to get a desired patient state with conditions applied.) The SDK provides multiple tested patient files for use in the bin/patients directory. For more information on this look at the Patient Methodology.

Engine Configuration

You can provide an engine configuration to the initialize methods. This configuration is used to tweek various variables associated in the BioGears methodology. Configuration modification requires a very indepth knowledge of the engine. It is not recommended to provide another configuration unless you know what effects it will have. There are some useful configuration options that may be of interest, such as writing data to a csv file while the initialization algorithm executes. Come visit us on the forums if this is something you want to know more about.

You can retrieve and view the configuration with this method (note you will need to cast it to the BioGearsConfiguration class to see all configuration data)

1 //--------------------------------------------------------------------------------------------------
2 /// \brief
3 /// returns the engine configuration.
4 //--------------------------------------------------------------------------------------------------
5 virtual const PhysiologyEngineConfiguration* GetConfiguration() = 0;

Data Tracking

BioGears has the ability to write specifically requested data to a comma seperated text file as the engine advances time. These csv file are very helpful in debugging and ensuring BioGears is modeling correctly. How to utilize this functionality is demonstrated in all the HowTo files provided in the SDK.

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// Retrieve the PhysiologyEngineTrack associated with tracking data from this engine to a file
4  //--------------------------------------------------------------------------------------------------
5  virtual PhysiologyEngineTrack* GetEngineTrack() = 0;

Advancing The Simulation In Time

Once the engine is initialized, it is ready to accept direction. The engine does not advance time on its own, you must explictly tell the engine to simulate a specific amount of time. There is a HowTo example that shows how to encapsulate the engine in a thread class that automatically advances time and processes actions. How you decide to drive the simulation is up to you, but you must explicitly advance time inorder for the models to simulate physiology.

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// executes one pass through the time loop of the engine at the fixed timestep
4  ///
5  /// Events, errors, and warning as are logged to file not errors are returned
6  /// through the API at this time.
7  ///
8  //--------------------------------------------------------------------------------------------------
9  virtual void AdvanceModelTime() = 0;
10 
11  //--------------------------------------------------------------------------------------------------
12  /// \brief
13  /// executes one pass through the time loop of the engine at the fixed timestep
14  ///
15  /// Events, errors, and warning as are logged to file not errors are returned
16  /// through the API at this time.
17  ///
18  //--------------------------------------------------------------------------------------------------
19  virtual void AdvanceModelTime(double time, const TimeUnit& unit) = 0;

If no time is provided, the engine will simulate for the smallest amount of time it can. The minimum amount of time the engine can simulate is the engines' time step, you can retrieve this duration with this method:

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// returns the engine time step that is used when advancing time.
4  ///
5  //--------------------------------------------------------------------------------------------------
6  virtual double GetTimeStep(const TimeUnit& unit) = 0;

You can retrieve the total amount of time the engine has simulated with the following call:

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// returns the current time of the simulation.
4  //--------------------------------------------------------------------------------------------------
5  virtual double GetSimulationTime(const TimeUnit& unit) = 0;

Note that the simulation time is 0 when the InitializeEngine method returns. Remember that you can set the simulation time to what ever you want when loading a state. It will then be incremented from that point on whenever you call AdvanceModelTime.

Process Action

Actions are the means by which instructions are provided to a physiology engine. You will need to create an instance of an action class, fill it out with the necessary data and pass it into this method.

1 //--------------------------------------------------------------------------------------------------
2 /// \brief
3 /// Execute the provided action.
4 /// true will be returned if the engine supports the action
5 /// false will be returned if the engine does not support the action
6 ///
7 //--------------------------------------------------------------------------------------------------
8 virtual bool ProcessAction(const SEAction& action) = 0;

Patient Actions

Environment Actions

Anesthesia Machine Actions

Inhaler Actions

Patient State

Once you start advancing time and processing actions, the patient state can start to change. Depending on what actions you process, it can change slightly, such as a slight increase in mean arterial pressure, or it can change quite dramatically and start affecting multiple systems through various physiological feedback mechanisms. These dramatic changes in patient state are tracked by means of Patient Events.

You can track patient event states in one of two ways.

  • Poll the patient object via Patient object method:
    1 //--------------------------------------------------------------------------------------------------
    2  /// \brief
    3  /// Returns the patient object used by the engine
    4  ///
    5  //--------------------------------------------------------------------------------------------------
    6  virtual const SEPatient& GetPatient() = 0;
    Note you can get more Patient data from this class, not just event status.
  • Set up a callback method that will automatically call your code when patient event status changes. Set the callback method with this method
    1 //--------------------------------------------------------------------------------------------------
    2  /// \brief
    3  /// Add a callback object that will be called whenever a pateint or anesthesia machine event changes state
    4  //--------------------------------------------------------------------------------------------------
    5  virtual void SetEventHandler(SEEventHandler* handler) = 0;

Event State is primarily associated with the patient, but there are events associated with Anesthesia Machine.

Look at the SDK HowTo-UseEngine.cpp for a full example in using both of these methods.

Patient Assessments

Patient assessments are intended to give general patient overviews, formed at the level of a clinician's report. The following assessments are availiable from BioGears:

You must create and provide an assessment object to the physiology engine via this method:
Note that assessments could add extra comupation time to gather and format data for the assessment.

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// Determines the assessment type and fills the data object with current data.
4  ///
5  /// Assessments can be queried at any point in the calculation and as many times are desired.
6  ///
7  //--------------------------------------------------------------------------------------------------
8  virtual bool GetPatientAssessment(SEPatientAssessment& assessment) = 0;

Systems Data

The bodies physiology, equipment, and the environment are all systems and each system has a method to retrieve its associated class in order to access this system data.

BioGears supports the following systems:

Code Method CDM Table
1 virtual const SEEnvironment* GetEnvironment() = 0;
Environment
1 virtual const SEBloodChemistrySystem* GetBloodChemistrySystem() = 0;
BloodChemistry
1 virtual const SECardiovascularSystem* GetCardiovascularSystem() = 0;
Cardiovascular
1 virtual const SEEndocrineSystem* GetEndocrineSystem() = 0;
Endocrine
1 virtual const SEEnergySystem* GetEnergySystem() = 0;
Energy
1 virtual const SERenalSystem* GetRenalSystem() = 0;
Renal
1 virtual const SEGastrointestinalSystem* GetGastrointestinalSystem() = 0;
Gastrointestinal
1 virtual const SENervousSystem* GetNervousSystem() = 0;
Nervous
1 virtual const SERespiratorySystem* GetRespiratorySystem() = 0;
Respiratory
1 virtual const SEDrugSystem* GetDrugSystem() = 0;
Drug
1 virtual const SETissueSystem* GetTissueSystem() = 0;
Tissue
1 virtual const SEAnesthesiaMachine* GetAnesthesiaMachine() = 0;
Anesthesia Machine
1 virtual const SEElectroCardioGram* GetElectroCardioGram() = 0;
ElectroCardioGram
1 virtual const SEInhaler* GetInhaler() = 0;
Inhaler
1 virtual const SEHepaticSystem* GetHepaticSystem() = 0;
Hepatic

Compartments

A compartment represents the fluid dynamics of an anatomical organ or equipment component. Comparments can represent various fidelities of data for these compoenents, such as:

  • An anatomical space, such as the body's skin, muscles
  • An organ, such as the liver
  • An organ substructure, such as the Left Heart
  • Extravascular tissue of an organ
  • A component of a piece of equipment, such as an anesthesia machine ventillator

The following compartment types are used to represent various anatomical structures for both physiology and equipment:

Various comparments can be used to represent a parent/child hierarcical structure, and comparments can be a parent for one or more child compartments. Parent compartments agregate data from their children, such as the parent compartment volume is simply the sum of each of its childrens' volume.
For eample, the heart has the following hierarchy :

  • Heart
    • Myocardium
    • Right Heart
    • Left Heart
    • Pericardium

Compartments also contain a substance quatity for each substance in the compartment as it moves through the body/equipment.
The following types are used to hold compartment substance information

The enumerations for compartments available in BioGears is found in the BioGearsPhysiologyEngine.h file. As these are programatic enumerations, you can use the auto-complete feature of your favorite programming IDE to view these enumerations as you code. BioGears discritizes it's compartments into enumerations based on fluid type and equipment. Here is a list of the various enumerated compartment names:

As we make changes to models, some of the naming/hierarchy of compartments used by BioGears could change, it's best to refer to the code file itself for the latest list of available compartments and their hierarchy.

Note that there are both liquid and gas compartments available for pulmonary spaces. The gas compartments represent the air flow and gaseous substances through the pulmonary tract. The liquid compartments represent the air flow and aerosolized liquid/solid substances through the pulmonary tract.

All compartments are accessed via the SECompartmentManager retrieved from this method:

1 //--------------------------------------------------------------------------------------------------
2 /// \brief
3 /// Retrieves the engine compartments, providing such data as:
4 /// flows, pressure, volume as well as substance volumes and volume fractions.
5 ///
6 //--------------------------------------------------------------------------------------------------
7 virtual const SECompartmentManager& GetCompartments() = 0;

Substances

Various Substances are available in the body and there is a SESubstanceManager associated with the engine.
You can retrieve the SESubstanceManager with this method:

1 //--------------------------------------------------------------------------------------------------
2  /// \brief
3  /// Retrieves the associated substance manager.
4  ///
5  //--------------------------------------------------------------------------------------------------
6  virtual SESubstanceManager& GetSubstanceManager() = 0;

In practice, only a substance reference are used with compartments to get the Substance Quantity object associated with a particular compartment. The data contained in the substance definition is primarily used in engine methodology, but there may be substance data you maybe interested in, such as the Partition Coefficient of a substance.