Skip to content

Commit f43fb75

Browse files
ajbairdStevenAWhite
authored andcommitted
adding new induction howto for paper
1 parent 3b1182a commit f43fb75

File tree

2 files changed

+459
-0
lines changed

2 files changed

+459
-0
lines changed
Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
/**************************************************************************************
2+
Copyright 2015 Applied Research Associates, Inc.
3+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4+
this file except in compliance with the License. You may obtain a copy of the License
5+
at:
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
specific language governing permissions and limitations under the License.
11+
**************************************************************************************/
12+
13+
#include "HowTo-induction.h"
14+
#include <iostream>
15+
16+
// Include the various types you will be using in your code
17+
#include <biogears/cdm/compartment/SECompartmentManager.h>
18+
#include <biogears/cdm/engine/PhysiologyEngineTrack.h>
19+
#include <biogears/cdm/patient/assessments/SEArterialBloodGasAnalysis.h>
20+
#include <biogears/cdm/patient/SEPatient.h>
21+
#include <biogears/cdm/patient/actions/SEHemorrhage.h>
22+
#include <biogears/cdm/patient/actions/SEPainStimulus.h>
23+
#include <biogears/cdm/patient/actions/SESubstanceBolus.h>
24+
#include <biogears/cdm/patient/actions/SESubstanceCompoundInfusion.h>
25+
#include <biogears/cdm/patient/actions/SESubstanceInfusion.h>
26+
#include <biogears/cdm/properties/SEScalarTypes.h>
27+
#include <biogears/cdm/substance/SESubstanceManager.h>
28+
#include <biogears/cdm/system/physiology/SEBloodChemistrySystem.h>
29+
#include <biogears/cdm/system/physiology/SECardiovascularSystem.h>
30+
#include <biogears/cdm/system/physiology/SERenalSystem.h>
31+
#include <biogears/cdm/system/physiology/SERespiratorySystem.h>
32+
#include <biogears/cdm/utils/SEEventHandler.h>
33+
#include <biogears/engine/BioGearsPhysiologyEngine.h>
34+
#include <biogears/string/manipulation.h>
35+
#include <filesystem>
36+
37+
38+
namespace fs = std::filesystem;
39+
40+
int main(int argc, char* argv[])
41+
{
42+
// To run multiple hemorrhages
43+
double lowestBloodFlow_mL_Per_min = 50.0;
44+
double highestBloodFlow_mL_Per_min = 200.0;
45+
double flowIncrement = 25.0;
46+
std::filesystem::path states = "./states";
47+
std::string state;
48+
49+
for (const auto& dirEntry : fs::recursive_directory_iterator(states, std::filesystem::directory_options::skip_permission_denied)) {
50+
std::cout << dirEntry << std::endl;
51+
state = dirEntry.path().filename().string();
52+
std::string logName = "./inductionData/HowToHemorrhagepHValidation";
53+
logName.append(state);
54+
logName.append(".log");
55+
InductionThread induction(logName, state);
56+
induction.AdministerInduction();
57+
}
58+
}
59+
}
60+
61+
62+
using namespace biogears;
63+
64+
InductionThread::InductionThread(const std::string logFile, std::string stateFile)
65+
: m_inductionThread()
66+
{
67+
//Create the engine and load patient state
68+
m_bg = CreateBioGearsEngine(logFile);
69+
m_bg->GetLogger()->Info(asprintf("Initiating %f %s", logFile, "% hemorrhage flow rate, for patient"));
70+
std::string statePath = "./states/";
71+
statePath.append(stateFile);
72+
m_bg->GetLogger()->Info(statePath);
73+
if (!m_bg->LoadState(statePath)) {
74+
m_bg->GetLogger()->Error("Could not load state, check the error");
75+
throw std::runtime_error("Could not load state, check the error");
76+
}
77+
78+
//Create CSV results file and set up data that we want to be tracked (tracking done in AdvanceModelTime)
79+
std::string resultsFileInduction = std::to_string(dochem);
80+
std::string resultsFile = "./inductionData/HowToInduction";
81+
resultsFile.append(resultsFileInduction);
82+
resultsFile.append(stateFile);
83+
resultsFile.append(".csv");
84+
85+
//Load substances and compounds
86+
SESubstance* vas = m_bg->GetSubstanceManager().GetSubstance("Vasopressin");
87+
SESubstance* lactate = m_bg->GetSubstanceManager().GetSubstance("Lactate");
88+
89+
//we will perform a 1:1:1 infusion ration during our mtp
90+
SESubstanceCompound* ringers = m_bg->GetSubstanceManager().GetCompound("RingersLactate");
91+
SESubstanceCompound* blood = m_bg->GetSubstanceManager().GetCompound("Blood_ONegative");
92+
SESubstanceCompound* plasma = m_bg->GetSubstanceManager().GetCompound("Plasma");
93+
SESubstanceCompound* platelets = m_bg->GetSubstanceManager().GetCompound("PlateletsInfusion");
94+
95+
96+
//Create infusion and bolus actions
97+
m_ringers = new SESubstanceCompoundInfusion(*ringers);
98+
m_blood = new SESubstanceCompoundInfusion(*blood);
99+
m_plasma = new SESubstanceCompoundInfusion(*plasma);
100+
m_platelet = new SESubstanceCompoundInfusion(*platelets);
101+
m_VasopressinBolus = new SESubstanceBolus(*vas);
102+
103+
//initialize trackers to 0
104+
m_ivBagVolume_mL = 0.0;
105+
m_ivBagVolumeBlood_mL = 0.0;
106+
m_ivBagVolumePlasma_mL = 0.0;
107+
m_ivBagVolumePlatelet_mL = 0.0;
108+
109+
m_bg->GetEngineTrack()->GetDataRequestManager().SetResultsFilename(resultsFile); //deposits in build/runtime
110+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("HeartRate", "1/min");
111+
m_bg->GetEngineTrack()->GetDataRequestManager().CreateSubstanceDataRequest().Set(*vas, "PlasmaConcentration", MassPerVolumeUnit::ug_Per_L);
112+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("ArterialBloodPH", "unitless");
113+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("CardiacOutput", "mL/min");
114+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("InflammatoryResponse-TissueIntegrity");
115+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("MeanArterialPressure", "mmHg");
116+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("SystolicArterialPressure", "mmHg");
117+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("DiastolicArterialPressure", "mmHg");
118+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("EndTidalCarbonDioxideFraction", "unitless");
119+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("RespirationRate", "1/min");
120+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("GlomerularFiltrationRate", "mL/min");
121+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("TidalVolume", "mL");
122+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("SystemicVascularResistance", "mmHg s/mL");
123+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("StrongIonDifference", "mmol/L");
124+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("BloodVolume", "mL");
125+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("MeanUrineOutput", "mL/hr");
126+
m_bg->GetEngineTrack()->GetDataRequestManager().CreatePhysiologyDataRequest().Set("PainVisualAnalogueScale");
127+
m_bg->GetEngineTrack()->GetDataRequestManager().CreateLiquidCompartmentDataRequest().Set("VenaCava", *lactate, "Molarity", AmountPerVolumeUnit::mmol_Per_L);
128+
m_bg->GetEngineTrack()->GetDataRequestManager().CreateLiquidCompartmentDataRequest().Set("Aorta", "OutFlow", VolumePerTimeUnit::mL_Per_min);
129+
m_bg->GetEngineTrack()->GetDataRequestManager().CreateSubstanceDataRequest().Set(*lactate, "Clearance-RenalClearance", VolumePerTimeMassUnit::mL_Per_min_kg);
130+
m_bg->GetEngineTrack()->GetDataTrack().Probe("totalFluid_mL", m_TotalVolume_mL);
131+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolume_mL", m_ivBagVolume_mL);
132+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolumeBlood_mL", m_ivBagVolumeBlood_mL);
133+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolumePlasma_mL", m_ivBagVolumePlasma_mL);
134+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolumePlatelet_mL", m_ivBagVolumePlatelet_mL);
135+
136+
m_runThread = true;
137+
}
138+
139+
InductionThread::~InductionThread()
140+
{
141+
m_runThread = false;
142+
std::this_thread::sleep_for(std::chrono::seconds(2));
143+
SAFE_DELETE(m_VasopressinBolus);
144+
SAFE_DELETE(m_ringers);
145+
SAFE_DELETE(m_blood);
146+
SAFE_DELETE(m_plasma);
147+
SAFE_DELETE(m_platelet);
148+
}
149+
150+
void InductionThread::AdministerVasopressin(double& bolus)
151+
{
152+
m_VasopressinBolus->SetAdminRoute(CDM::enumBolusAdministration::Intravenous);
153+
m_VasopressinBolus->GetConcentration().SetValue(1.0, MassPerVolumeUnit::mg_Per_mL);
154+
m_VasopressinBolus->GetDose().SetValue(bolus, VolumeUnit::mL);
155+
m_mutex.lock();
156+
m_bg->ProcessAction(*m_VasopressinBolus);
157+
m_mutex.unlock();
158+
}
159+
160+
void InductionThread::SetRingersInfusionRate(double& volume, double& rate)
161+
{
162+
m_ringers->GetBagVolume().SetValue(volume, VolumeUnit::mL);
163+
m_ringers->GetRate().SetValue(rate, VolumePerTimeUnit::mL_Per_hr);
164+
m_ivBagVolume_mL = volume;
165+
m_mutex.lock();
166+
m_bg->ProcessAction(*m_ringers);
167+
m_mutex.unlock();
168+
}
169+
170+
void InductionThread::SetBloodInfusionRate(double& volume, double& rate)
171+
{
172+
m_blood->GetBagVolume().SetValue(volume, VolumeUnit::mL);
173+
m_blood->GetRate().SetValue(rate, VolumePerTimeUnit::mL_Per_hr);
174+
m_ivBagVolumeBlood_mL = volume;
175+
m_mutex.lock();
176+
m_bg->ProcessAction(*m_blood);
177+
m_mutex.unlock();
178+
}
179+
180+
void InductionThread::SetPlasmaInfusionRate(double& volume, double& rate)
181+
{
182+
m_plasma->GetBagVolume().SetValue(volume, VolumeUnit::mL);
183+
m_plasma->GetRate().SetValue(rate, VolumePerTimeUnit::mL_Per_min);
184+
m_ivBagVolumePlasma_mL = volume;
185+
m_mutex.lock();
186+
m_bg->ProcessAction(*m_plasma);
187+
m_mutex.unlock();
188+
}
189+
190+
void InductionThread::SetPlateletInfusionRate(double& volume, double& rate)
191+
{
192+
m_platelet->GetBagVolume().SetValue(volume, VolumeUnit::mL);
193+
m_platelet->GetRate().SetValue(rate, VolumePerTimeUnit::mL_Per_hr);
194+
m_ivBagVolumePlatelet_mL = volume;
195+
m_mutex.lock();
196+
m_bg->ProcessAction(*m_blood);
197+
m_mutex.unlock();
198+
}
199+
200+
void InductionThread::AdvanceTimeFluids()
201+
{
202+
m_mutex.lock();
203+
m_bg->AdvanceModelTime(1.0, TimeUnit::s);
204+
if (m_blood->HasBagVolume() && m_blood->HasRate()) {
205+
m_TotalVolume_mL += (m_blood->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
206+
m_TotalVolumeBlood_mL += (m_blood->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
207+
m_ivBagVolumeBlood_mL += (-m_blood->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
208+
if (m_ivBagVolumeBlood_mL < 0.0) {
209+
m_bg->GetLogger()->Info("blood bag is empty \n");
210+
m_ivBagVolumeBlood_mL = 0.0;
211+
m_blood->Clear();
212+
}
213+
}
214+
//repeat for plasma
215+
if (m_plasma->HasBagVolume() && m_plasma->HasRate()) {
216+
m_TotalVolume_mL += (m_plasma->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
217+
m_TotalVolumePlasma_mL += (m_plasma->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
218+
m_ivBagVolumePlasma_mL += (-m_plasma->GetRate().GetValue(VolumePerTimeUnit::mL_Per_s));
219+
if (m_ivBagVolumePlasma_mL < 0.0) {
220+
m_bg->GetLogger()->Info("blood bag is empty \n");
221+
m_ivBagVolumePlasma_mL = 0.0;
222+
m_plasma->Clear();
223+
}
224+
}
225+
m_bg->GetEngineTrack()->GetDataTrack().Probe("totalFluid_mL", m_TotalVolume_mL);
226+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolume_mL", m_ivBagVolume_mL);
227+
m_bg->GetEngineTrack()->GetDataTrack().Probe("totalFluidBlood_mL", m_TotalVolumeBlood_mL);
228+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolumeBlood_mL", m_ivBagVolumeBlood_mL);
229+
m_bg->GetEngineTrack()->GetDataTrack().Probe("totalFluidPlasma_mL", m_TotalVolumePlasma_mL);
230+
m_bg->GetEngineTrack()->GetDataTrack().Probe("bagVolumePlasma_mL", m_ivBagVolumePlasma_mL);
231+
m_bg->GetEngineTrack()->TrackData(m_bg->GetSimulationTime(TimeUnit::s));
232+
m_mutex.unlock();
233+
std::this_thread::sleep_for(std::chrono::milliseconds(25));
234+
}
235+
236+
void InductionThread::Status()
237+
{
238+
m_mutex.lock();
239+
m_bg->GetLogger()->Info(asprintf("The patient suffered a hemorrhage wound %f %s", m_bg->GetSimulationTime(TimeUnit::min), " min ago"));
240+
m_bg->GetLogger()->Info(asprintf("Tidal Volume : %f %s", m_bg->GetRespiratorySystem()->GetTidalVolume(VolumeUnit::mL), "mL"));
241+
m_bg->GetLogger()->Info(asprintf("Systolic Pressure : %f %s", m_bg->GetCardiovascularSystem()->GetSystolicArterialPressure(PressureUnit::mmHg), "mmHg"));
242+
m_bg->GetLogger()->Info(asprintf("Diastolic Pressure : %f %s", m_bg->GetCardiovascularSystem()->GetDiastolicArterialPressure(PressureUnit::mmHg), "mmHg"));
243+
m_bg->GetLogger()->Info(asprintf("Heart Rate : %f %s", m_bg->GetCardiovascularSystem()->GetHeartRate(FrequencyUnit::Per_min), "bpm"));
244+
m_bg->GetLogger()->Info(asprintf("Respiration Rate : %f %s", m_bg->GetRespiratorySystem()->GetRespirationRate(FrequencyUnit::Per_min), "bpm"));
245+
m_bg->GetLogger()->Info(asprintf("Oxygen Saturation : %f", m_bg->GetBloodChemistrySystem()->GetOxygenSaturation()));
246+
m_bg->GetLogger()->Info(asprintf("Blood Volume: %f %s", m_bg->GetCardiovascularSystem()->GetBloodVolume(VolumeUnit::mL), "mL"));
247+
m_bg->GetLogger()->Info(asprintf("Systemic Vascular Resistance : %f %s", m_bg->GetCardiovascularSystem()->GetSystemicVascularResistance(FlowResistanceUnit::mmHg_s_Per_mL), "mmHg_s_Per_mL"));
248+
m_bg->GetLogger()->Info(asprintf("Mean Urine Output : %f %s", m_bg->GetRenalSystem()->GetMeanUrineOutput(VolumePerTimeUnit::mL_Per_hr), "mL_Per_hr"));
249+
if (m_ringers->HasBagVolume()) {
250+
m_bg->GetLogger()->Info(asprintf("Remaining blood Volume in bag: %f %s", m_ivBagVolumeBlood_mL, "mL"));
251+
}
252+
253+
std::cout << std::endl;
254+
m_mutex.unlock();
255+
}
256+
257+
void AdministerInduction();
258+
{
259+
const SEPatient& patient = m_bg->GetPatient();
260+
double weight_kg = patient.GetWeight(MassUnit::kg);
261+
}
262+
263+
264+
//routine to administer fluids with a goal directed therapy for urine ourput
265+
void InductionThread::FluidLoading()
266+
{
267+
//redblood cell unit volume:
268+
double pRBCVolume_mL = 350;
269+
270+
//plasma unit volume
271+
double plasmaVolume_mL = 200;
272+
273+
//platlet volume
274+
double platletVolume_mL = 300;
275+
276+
//rates:
277+
double bloodRate_mL_Per_hr = 250;
278+
double plasmaRate_mL_Per_min = 15;
279+
280+
//we will activate the protocol when shock index reaches 1:
281+
double shockIndex = 0.0;
282+
283+
//shock index requires the heart rate and the systolic pressure:
284+
double heartRate_min = m_bg->GetCardiovascularSystem()->GetHeartRate(FrequencyUnit::Per_min);
285+
double systolicPressure_mmHg = m_bg->GetCardiovascularSystem()->GetSystolicArterialPressure(PressureUnit::mmHg);
286+
287+
//update shock index:
288+
shockIndex = heartRate_min / systolicPressure_mmHg;
289+
290+
//time keeping
291+
int checkTime_s = 3600;
292+
int LabTime_s = 1800; // 60 mins
293+
double volume = 0.0;
294+
295+
//how long do we want to run for?
296+
double maxSimTime_hr = 2.0;
297+
double hemTime_min = 20.0;
298+
299+
//compute urine production and max fluid requirements, per parkland formula
300+
const SEPatient& patient = m_bg->GetPatient();
301+
double weight_kg = patient.GetWeight(MassUnit::kg);
302+
303+
double initialInfustion_mL_Per_hr = 0.0; //tbsa * 10.0; // Should start at 10*tbsa // (DayLimit_mL / 0.5) / 8.0; //half of the fluid should be loaded in the first 8 hours;
304+
double initialInfustionAlbumin_mL_Per_hr = 50.0; //tbsa * 10.0; // Should start at 10*tbsa // (DayLimit_mL / 0.5) / 8.0; //half of the fluid should be loaded in the first 8 hours;
305+
double temp = 0.0;
306+
bool Labs = true;
307+
bool fluidOn = false;
308+
309+
m_bg->GetLogger()->Info(asprintf("Beginning care"));
310+
311+
while (m_runThread) {
312+
//pull the data
313+
314+
//check for bleeding intervention:
315+
if (m_bg->GetSimulationTime(TimeUnit::min) > hemTime_min && m_hemorrhage->GetInitialRate().GetValue(VolumePerTimeUnit::mL_Per_min) > ZERO_APPROX) {
316+
m_hemorrhage->GetInitialRate().SetValue(0, VolumePerTimeUnit::mL_Per_min);
317+
m_bg->ProcessAction(*m_hemorrhage);
318+
}
319+
heartRate_min = m_bg->GetCardiovascularSystem()->GetHeartRate(FrequencyUnit::Per_min);
320+
systolicPressure_mmHg = m_bg->GetCardiovascularSystem()->GetSystolicArterialPressure(PressureUnit::mmHg);
321+
322+
shockIndex = heartRate_min / systolicPressure_mmHg;
323+
324+
if (shockIndex >= 1.0) {
325+
fluidOn = true;
326+
}
327+
328+
//initial fluids:
329+
if (fluidOn && m_ivBagVolumeBlood_mL == 0.0 && m_ivBagVolumePlasma_mL == 0.0) {
330+
//set 1:1 fluid infusion:
331+
SetPlasmaInfusionRate(plasmaVolume_mL, plasmaRate_mL_Per_min);
332+
SetBloodInfusionRate(pRBCVolume_mL, bloodRate_mL_Per_hr);
333+
m_bg->GetLogger()->Info(asprintf("Beginning Intervention with infusion at %f %s", bloodRate_mL_Per_hr, "mL_Per_hr"));
334+
}
335+
336+
// Generate blood gas amount of time
337+
if (((int)m_bg->GetSimulationTime(TimeUnit::s) + 1) % LabTime_s == 0 && Labs == true) {
338+
//run our blood gas assesment every hour:
339+
m_bg->GetPatientAssessment(bga);
340+
m_bg->GetLogger()->Info(asprintf("Checked blood/gas Labs"));
341+
}
342+
343+
//check status every hour, reset the volume while we are at it
344+
if (((int)m_bg->GetSimulationTime(TimeUnit::s) + 1) % checkTime_s == 0) {
345+
Status();
346+
}
347+
348+
// make sure that the bag is full
349+
if (m_ivBagVolumeBlood_mL < 1.0 && fluidOn) {
350+
m_blood->GetBagVolume().SetValue(pRBCVolume_mL, VolumeUnit::mL);
351+
m_bg->GetLogger()->Info("blood IV bag is low, refilling bag \n");
352+
m_bg->ProcessAction(*m_blood);
353+
m_ivBagVolumeBlood_mL = pRBCVolume_mL; //tracking purposes
354+
}
355+
// make sure that the plasma bag is full
356+
if (m_ivBagVolumePlasma_mL < 1.0 && fluidOn) {
357+
m_plasma->GetBagVolume().SetValue(plasmaVolume_mL, VolumeUnit::mL);
358+
m_bg->GetLogger()->Info("blood IV bag is low, refilling bag \n");
359+
m_bg->ProcessAction(*m_blood);
360+
m_ivBagVolumePlasma_mL = plasmaVolume_mL; //tracking purposes
361+
}
362+
363+
//exit checks:
364+
if (m_bg->GetPatient().IsEventActive(CDM::enumPatientEvent::IrreversibleState)) {
365+
//m_bg->GetLogger()->Info(std::stringstream() << "oh no!");
366+
m_bg->GetLogger()->Info("///////////////////////////////////////////////////////////////");
367+
m_runThread = false;
368+
}
369+
370+
if (m_bg->GetSimulationTime(TimeUnit::hr) > maxSimTime_hr) {
371+
m_bg->GetLogger()->Info("This simulation has gone on too long");
372+
m_runThread = false;
373+
}
374+
375+
//advance time
376+
AdvanceTime();
377+
}
378+
}
379+

0 commit comments

Comments
 (0)