SimEngine.cpp 9.75 KB
Newer Older
fmg005's avatar
fmg005 committed
1
2
3
#include <iostream>
#include <string>
#include <thread>
4
5
#include <vector>
#include <map>
pkda001's avatar
pkda001 committed
6
#include <libconfig.h>
7
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
fmg005's avatar
fmg005 committed
8
9
10
11
12
13
14
15
16
17
18

#include "Pump.h"
#include "Monitor.h"
#include "Controller.h"
#include "Environment.h"
#include "PhysiologyData.h"
#include "SimulationLogger.h"
#include "SimEngine.h"


// Include the various types you will be using in your code
19
#include "scenario/SEDataRequestManager.h"
fmg005's avatar
fmg005 committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "patient/actions/SEHemorrhage.h"
#include "patient/actions/SESubstanceCompoundInfusion.h"
#include "system/physiology/SEBloodChemistrySystem.h"
#include "system/physiology/SECardiovascularSystem.h"
#include "system/physiology/SEEnergySystem.h"
#include "system/physiology/SERespiratorySystem.h"
#include "substance/SESubstanceManager.h"
#include "substance/SESubstanceCompound.h"
#include "properties/SEScalar0To1.h"
#include "properties/SEScalarFrequency.h"
#include "properties/SEScalarMass.h"
#include "properties/SEScalarMassPerVolume.h"
#include "properties/SEScalarPressure.h"
#include "properties/SEScalarTemperature.h"
#include "properties/SEScalarTime.h"
#include "properties/SEScalarVolume.h"
#include "properties/SEScalarVolumePerTime.h"
#include "engine/SEEngineTracker.h"
#include "compartment/SECompartmentManager.h"

//--------------------------------------------------------------------------------------------------
/// \brief
/// Usage for applying a Hemorrhage insult to the patient
///
/// \details
/// Refer to the SEHemorrhage class
/// Refer to the SESubstanceManager class
/// Refer to the SESubstanceIVFluids class for applying an IV to the patient
//--------------------------------------------------------------------------------------------------


using namespace libconfig;

53
54
int main(int argc, char * argv[]){

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

	    clock_t t1, t2, sim_run_time;
	    vector<string> patients_list;
	    auto cf = std::make_shared<Config>();
	    float sim_time_secs, sim_time_mins;
	    string f_path = clasim_config_dir+"scenario.cfg";
	    const char* filepath = f_path.c_str();

	    try
	    {
			    cf->readFile(filepath);
	    }

	    catch(const FileIOException &fioex) {
			    std::cerr << "I/O error while reading file: " << filepath << std::endl;
			    //return(EXIT_FAILURE);
	    }

	    catch(const ParseException &pex) {
			    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
				    << " - " << pex.getError() << std::endl;
			    //return(EXIT_FAILURE);
	    }

	    patients_list = get_global_patients(cf);

	    for(auto patient: patients_list) {
		    // start timer
		    t1 = clock();

		    //Simulation input : Name of patient
		    Simulation(patient, cf);

		    //stop timer
		    t2 = clock();

		    sim_run_time = t2 - t1;
		    sim_time_secs = ((float)sim_run_time)/CLOCKS_PER_SEC;
		    sim_time_mins = sim_time_secs/60.0;

		    cout << "\nThe Simulation for " << patient;
		    cout  << " took "<< sim_time_secs <<" seconds ";
		    cout <<"or " << sim_time_mins <<" minutes"<<endl;
            }


fmg005's avatar
fmg005 committed
101
102
}

103
void Simulation(const string patient_name, const std::shared_ptr<Config>& cf)
fmg005's avatar
fmg005 committed
104
105
{

106
	  	// Create the engine and load the patient
107
108
	  	std::unique_ptr<PhysiologyEngine> pe =
CreatePulseEngine(clasim_results_dir+"SimulationEngine_"+patient_name+".log");
109
110
	  	pe->GetLogger()->Info("CMD Simulation");
	  	//if (!pe->LoadStateFile("./states/StandardMale@0s.pba"))
111
			if (!pe->LoadStateFile(pulse_state_dir+patient_name+"@0s.pba"))
112
113
114
115
	  	{
	    		pe->GetLogger()->Error("Could not load state, check the error");
	    		return;
	  	}
fmg005's avatar
fmg005 committed
116
117


118
119
120
121
122
123
		  // Create data requests for each value that should be written to the output log as the engine is executing
		  // Physiology System Names are defined on the System Objects
		  // defined in the Physiology.xsd file
		  pe->GetEngineTracker()->GetDataRequestManager().CreatePhysiologyDataRequest("HeartRate", FrequencyUnit::Per_min);
		  pe->GetEngineTracker()->GetDataRequestManager().CreatePhysiologyDataRequest("BloodVolume", VolumeUnit::mL);
		  pe->GetEngineTracker()->GetDataRequestManager().CreatePhysiologyDataRequest("MeanArterialPressure", PressureUnit::mmHg);
124
		  pe->GetEngineTracker()->GetDataRequestManager().SetResultsFilename(clasim_results_dir+"PulseSimEngine_"+patient_name+".txt");
fmg005's avatar
fmg005 committed
125

126
127
			//instatiate Hemorrhage Action
			SEHemorrhage hemorrhageLeg;
fmg005's avatar
fmg005 committed
128
129
			const double initialMAP = 70.0;
			double currentMAP;
fmg005's avatar
fmg005 committed
130

131
132
133
			//instatiate enviroment object
			CMD::Environment sim_env;
			PhysiologyData data;
fmg005's avatar
fmg005 committed
134

135
			// load simulation environment
136
			Global_LoadConfig(pe, cf, &sim_env);
fmg005's avatar
fmg005 committed
137

138
139
			// List of pumps
			map<string, Pump*> pumps;
fmg005's avatar
fmg005 committed
140

141
142
			//Iintialize Pump
			Pump pump_saline(&sim_env, &data, "Saline");
143
			pump_saline.LoadConfig(pe, cf);
fmg005's avatar
fmg005 committed
144

145
			Pump pump_bpdrug(&sim_env, &data, "Norepinephrine");
146
			pump_bpdrug.LoadConfig(pe, cf);
fmg005's avatar
fmg005 committed
147

148
			pumps.insert(make_pair("saline", &pump_saline));
149
			pumps.insert(make_pair("bpdrug", &pump_bpdrug));
fmg005's avatar
fmg005 committed
150

151
152
			//Initialize Controller
			Controller controller(&sim_env, &data, pumps);
153
			controller.LoadConfig(pe, cf);
fmg005's avatar
fmg005 committed
154
155


156
157
158
159
			//Initialize Monitor
			Monitor monitor(&sim_env, &data);
			// Call this member function before 'update member function'
			// to load new rate value from the config file
160
			monitor.LoadConfig(pe, cf);
fmg005's avatar
fmg005 committed
161
162


163
			//logger
164
165
			sim_env.logger =
std::make_shared<SimulationLogger>(clasim_results_dir+"SimulationEngineLog_"+patient_name+".txt");
fmg005's avatar
fmg005 committed
166

167
168
			bool STOP = false; // Execute stop hemmorrhage only once; without this it be executed for each timestep
			bool DEVICES_START = false;
fmg005's avatar
fmg005 committed
169

170
171
	    // stop when the set time is reached
		  while (sim_env.time_index <= sim_env.simulation_timesteps) {
fmg005's avatar
fmg005 committed
172

fmg005's avatar
fmg005 committed
173
174
					sim_env.sim_currentTime = pe->GetSimulationTime(TimeUnit::s);
					//cout << "sim time "<< sim_env.sim_currentTime <<endl;
175
176
177
					// event_hemorrage_start
					if(sim_env.time_index == sim_env.simulation_injury_start_timestep ){
						// Hemorrhage Starts - instantiate a hemorrhage action and have the engine 		process it
fmg005's avatar
fmg005 committed
178

179
								cout << "\nHemorrhage Started at: " << pe->GetSimulationTime(TimeUnit::s) << endl;
fmg005's avatar
fmg005 committed
180

181
182
183
								//the location 		of the hemorrhage
				  			hemorrhageLeg.SetCompartment(pulse::VascularCompartment::RightLeg);
								//the rate of hemorrhage
184
								hemorrhageLeg.GetRate().SetValue(150,VolumePerTimeUnit::mL_Per_min);
185
				  			pe->ProcessAction(hemorrhageLeg);
fmg005's avatar
fmg005 committed
186

187
188
								STOP = true;
					}
fmg005's avatar
fmg005 committed
189

fmg005's avatar
fmg005 committed
190
					currentMAP = pe->GetCardiovascularSystem()->GetMeanArterialPressure(PressureUnit::mmHg);
fmg005's avatar
fmg005 committed
191

fmg005's avatar
fmg005 committed
192
					if( currentMAP <= initialMAP && STOP){
fmg005's avatar
fmg005 committed
193

194
								cout << "\nHemorrhage Stoppd at: " << pe->GetSimulationTime(TimeUnit::s) << endl;
fmg005's avatar
fmg005 committed
195

196
197
198
199
200
								//the location 	of the hemorrhage
								hemorrhageLeg.SetCompartment(pulse::VascularCompartment::RightLeg);
								// Stop  hemorrhage
								hemorrhageLeg.GetRate().SetValue(0,VolumePerTimeUnit::mL_Per_min);
								pe->ProcessAction(hemorrhageLeg);
fmg005's avatar
fmg005 committed
201

202
								STOP = false;
fmg005's avatar
fmg005 committed
203

204
205
								// instruct devices to start
								DEVICES_START = true;
fmg005's avatar
fmg005 committed
206

207
208
								cout << "START DEVICES" << endl;
					}
fmg005's avatar
fmg005 committed
209

210
          if (DEVICES_START) {
fmg005's avatar
fmg005 committed
211

212
213
214
							  monitor.update(pe);
								controller.update(pe);
								pumps["saline"]->update(pe);
215
								pumps["bpdrug"]->update(pe);
fmg005's avatar
fmg005 committed
216

217
				  }
fmg005's avatar
fmg005 committed
218

219
220
   /*
					if( sim_env.time_index == sim_env.simulation_injury_stop_timestep ){
fmg005's avatar
fmg005 committed
221

222
								cout << "\nHemorrhage Stoppd at: " << pe->GetSimulationTime(TimeUnit::s) << endl;
fmg005's avatar
fmg005 committed
223

224
225
226
227
228
229
230
231
232
233
234
								//the location 	of the hemorrhage
								hemorrhageLeg.SetCompartment(pulse::VascularCompartment::RightLeg);
								// Stop  hemorrhage
								hemorrhageLeg.GetRate().SetValue(0,VolumePerTimeUnit::mL_Per_min);
								pe->ProcessAction(hemorrhageLeg);
					}
   */
					// track patient data
					pe->GetEngineTracker()->TrackData(pe->GetSimulationTime(TimeUnit::s));
					// Advance engine for each time step
					pe->AdvanceModelTime();
fmg005's avatar
fmg005 committed
235

236
237
					// increment environment time index whenever engine advances
					sim_env.time_index++;
fmg005's avatar
fmg005 committed
238

239
			}// End while looop
fmg005's avatar
fmg005 committed
240

241
242
243
}// End Simulation function


244
void Global_LoadConfig(std::unique_ptr<PhysiologyEngine>& engine, const std::shared_ptr<Config>& cf, CMD::Environment* env) {
fmg005's avatar
fmg005 committed
245

246
247
248
			/* get the simulation run time */
			try
			{
249
		  env->simulation_time = cf->lookup("simulation.time.run");
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
			}
			catch(const SettingNotFoundException) {
					cout << "Setting Not Found: simulation.time.run" << endl;
			}

			/* get the injury start time */
			try
			{
		  		env->simulation_injury_start = cf->lookup("simulation.time.injury_start");
			}
			catch(const SettingNotFoundException) {
					cout << "Setting Not Found: simulation.time.injury_start" << endl;
			}

			/* get the injury stop time */
			try
			{
		  	env->simulation_injury_stop = cf->lookup("simulation.time.injury_stop");
			}
			catch(const SettingNotFoundException) {
					cout << "Setting Not Found: simulation.time.injury_stop" << endl;
			}
272
273

			env->time_index = 0; // initialize the time index
fmg005's avatar
fmg005 committed
274
275
		  env->engine_timestep = engine->GetTimeStep(TimeUnit::s);
		  env->simulation_timesteps = env->simulation_time / env->engine_timestep;
276
277
			env->simulation_injury_start_timestep = env->simulation_injury_start / env->engine_timestep;
			env->simulation_injury_stop_timestep = env->simulation_injury_stop / env->engine_timestep;
fmg005's avatar
fmg005 committed
278
279
		  env->vector_index = 0;

fmg005's avatar
fmg005 committed
280
281
			env->sim_currentTime = engine->GetSimulationTime(TimeUnit::s);

fmg005's avatar
fmg005 committed
282
283
		  //env->logger = std::make_shared<SimulationLogger>("SimulatoinEngineLog.txt");

284
285
}// End Global_LoadConfig

286
vector<string> get_global_patients(const std::shared_ptr<Config>& cf){
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

			vector<string> patients;

			try{

					Setting& names = cf->lookup("simulation.patients.names");

					// Check if patient list is empty
					if (names.getLength() < 1) cout <<"Name List is empty"<<endl;

					for (Setting& name : names) {
							//use strlen to check if entered string isn't empty

							patients.push_back(string((const char*)name));
							//env->patient_names.push_back(string(p_name));
					}

			}
			catch(const SettingNotFoundException) {
306
					cout << "Setting Not Found: simulation.patients.names" << endl;
307
			}
fmg005's avatar
fmg005 committed
308

309
			return patients;
fmg005's avatar
fmg005 committed
310
}