Commit 758440e3 authored by fmg005's avatar fmg005

Initial commit

parents
cmake_minimum_required(VERSION 3.2)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "Install location")
# Policy to address @foo@ variable expansion
if(POLICY CMP0053)
cmake_policy(SET CMP0053 NEW)
endif()
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
message( STATUS "64 bits compiler detected" )
set( EX_CONFIG "" )
set(FIND_LIBRARY_USE_LIB64_PATHS ON)
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
message( STATUS "32 bits compiler detected" )
set( EX_CONFIG "32" )
set(FIND_LIBRARY_USE_LIB64_PATHS OFF)
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
SET(CONFIGURATION)
if(WIN32)
set(CONFIGURATION ${CMAKE_CFG_INTDIR})
else()
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
set(CONFIGURATION ${CMAKE_BUILD_TYPE})
endif()
string(TOLOWER ${CONFIGURATION} CONFIGURATION)
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo CACHE TYPE INTERNAL FORCE )
if(MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Ob2 /Oi /Od /RTC1" CACHE TYPE INTERNAL FORCE)
endif()
if(MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Wl,--kill-at -std=gnu++0x")#turn on C++11
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--kill-at")
endif()
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11 -stdlib=libc++")
endif()
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11 ")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:\$ORIGIN")
endif()
include(cmdsim.cmake)
project(CMD_SIM)
# header files
include_directories(include)
# source files
set(MY_SOURCE_FILES
src/SimEngine.cpp
src/Monitor.cpp
src/Controller.cpp
src/Pump.cpp
src/SimulationLogger.cpp
src/MedicalDevice.cpp
include/Environment.h
include/PhysiologyData.h
include/SimulationLogger.h
include/Monitor.h
include/Pump.h
include/Controller.h
include/MedicalDevice.h
)
source_group("" FILES ${MY_SOURCE_FILES})
set(SOURCE ${MY_SOURCE_FILES})
add_executable(HowToDriver EXCLUDE_FROM_ALL ${SOURCE})
# Preprocessor Definitions and Include Paths
set(FLAGS)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include/cdm)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include/bind)
set_target_properties(HowToDriver PROPERTIES COMPILE_FLAGS "${FLAGS}" PREFIX "")
# Dependent Libraries
if(WIN32)
set(lib_ext "lib")
set(log4cpp_prefix "")
else()
set(lib_ext "a")
set(log4cpp_prefix "lib")
endif()
set(D_LIB_FILES
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/PulseEngine.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/CommonDataModel.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/DataModelBindings.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/${log4cpp_prefix}log4cpp.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/libprotobufd.${lib_ext}
)
set(O_LIB_FILES
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/PulseEngine.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/CommonDataModel.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/DataModelBindings.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/${log4cpp_prefix}log4cpp.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/libprotobuf.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/libconfig++.${lib_ext}
)
foreach(file ${D_LIB_FILES})
target_link_libraries(HowToDriver debug ${file})
endforeach()
foreach(file ${O_LIB_FILES})
target_link_libraries(HowToDriver optimized ${file})
endforeach()
add_custom_command(TARGET HowToDriver POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${INSTALL_BIN}/${CONFIGURATION}${EX_CONFIG}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:HowToDriver> ${INSTALL_BIN}/${CONFIGURATION}${EX_CONFIG})
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <iostream>
#include <string>
#include <libconfig.h++>
#include <vector>
#include <algorithm>
#include <limits>
#include <math.h>
#include <cmath>
#include <stdlib.h> // srand()
#include <ctime>
#include "CommonDataModel.h"
#include "PulsePhysiologyEngine.h"
#include "Environment.h"
#include "PhysiologyData.h"
#include "Pump.h"
#include "system/physiology/SECardiovascularSystem.h"
#include "properties/SEScalarTime.h"
#include "properties/SEScalarVolumePerTime.h"
using namespace std;
using namespace libconfig;
class Controller {
private:
double controller_rate_Hz; // The rate at which device receives or sends data
double time_step;
int new_rate;
Config cfg; // API for accessing configuration files
const double MAX_RATE_Hz;
bool is_input_multiple;
//static const int array_sz;
int array_rate[4]; // for generating random rates
unsigned input_period;
static vector<PhysiologyData> patient_state;
Environment* m_env;
PhysiologyData* m_data;
public:
// Constructor
Controller(Environment*, PhysiologyData*);
Controller();
// Device logic will go in here
// This function uses the engine object to query required info
void update(std::unique_ptr<PhysiologyEngine>&);
// Load the configuration file to capture controller rate
void LoadConfig(std::unique_ptr<PhysiologyEngine>&, const char*);
static void SendValues(PhysiologyData&);
void GetData();
void Stop();
void SetRate(int, unsigned int);
// Destructor
~Controller();
};
#endif
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#include <memory>
#include "SimulationLogger.h"
struct Environment {
double engine_timestep; // engine period
double simulation_time; // grab from config file in seconds
unsigned long simulation_timesteps; // how long should simulation run
unsigned long time_index; // track engine advancement time
unsigned long vector_index; // track size of vector used to pass data between objects ie. vector<PhysiologyData>
unsigned long pump_index;
std::shared_ptr<SimulationLogger> logger;
};
#endif
#ifndef MEDICALDEVICE_H
#define MEDICALDEVICE_H
#include "CommonDataModel.h"
#include "PulsePhysiologyEngine.h"
#include <iostream>
#include <string>
#include <chrono>
#include <libconfig.h++>
#include "PhysiologyData.h"
#include "system/physiology/SECardiovascularSystem.h"
#include "properties/SEScalarFrequency.h"
using namespace std;
using namespace libconfig;
class MedicalDevice {
protected:
double m_rate_Hz; // The rate at which device receives or sends data
const double MAX_RATE_Hz; // Maximum rate in Hz at which data can be transfered
Config m_cfg; // API for accessing configuration files
public:
MedicalDevice();
// Device logic will go in here
// This function uses the engine object to query required info
virtual void update(std::unique_ptr<PhysiologyEngine>&);
// Load the configuration file to capture device rate
virtual void LoadConfig(std::unique_ptr<PhysiologyEngine>&, const char*);
// Destructor
~MedicalDevice();
};
#endif
#ifndef MONITOR_H
#define MONITOR_H
//#include "EngineHowTo.h"
#include "CommonDataModel.h"
#include "PulsePhysiologyEngine.h"
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <cmath>
#include <libconfig.h++>
#include "MedicalDevice.h"
#include "Controller.h"
#include "Environment.h"
#include "PhysiologyData.h"
#include "system/physiology/SECardiovascularSystem.h"
#include "properties/SEScalarTime.h"
#include "properties/SEScalarPressure.h"
#include "properties/SEScalarVolumePerTime.h"
#include "properties/SEScalarVolume.h"
using namespace std;
using namespace libconfig;
class Monitor : public MedicalDevice {
private:
bool is_input_multiple;
bool is_output_multiple;
bool HeartRate;
bool BloodPressure;
double output_rate_Hz;
double time_step;
double heart_rate;
unsigned int input_period;
unsigned int output_period;
Environment* m_env;
PhysiologyData* m_data;
public:
// Constructor
Monitor();
Monitor(Environment*, PhysiologyData*);
// Device logic will go in here
// This function uses the engine object to query required info
virtual void update(std::unique_ptr<PhysiologyEngine>&);
// Load the configuration file to capture device rate
virtual void LoadConfig(std::unique_ptr<PhysiologyEngine>&, const char*);
// Method to transfer physiological data to Controller
void SendData(PhysiologyData&);
void Stop();
// Destructor
~Monitor();
};
#endif
#ifndef PHYSIOLOGYDATA_H
#define PHYSIOLOGYDATA_H
struct PhysiologyData {
double heart_rate;
double pressure;
double blood_volume;
bool HeartRate;
bool BloodPressure;
bool BloodVolume;
};
#endif
#ifndef PUMP_H
#define PUMP_H
#include <iostream>
#include <string>
#include <utility>
#include <libconfig.h++>
#include <limits>
#include "MedicalDevice.h"
#include "Controller.h"
#include "Environment.h"
#include "PhysiologyData.h"
#include "patient/actions/SESubstanceCompoundInfusion.h"
#include "substance/SESubstanceManager.h"
#include "substance/SESubstanceCompound.h"
#include "properties/SEScalarVolume.h"
#include "properties/SEScalarVolumePerTime.h"
using namespace std;
using namespace libconfig;
class Pump : public MedicalDevice {
private:
bool is_input_multiple;
double pump_rate_Hz;
double pump_delay;
double time_step;
double delay_period;
unsigned long input_period;
unsigned long period;
int pump_rate;
static vector< pair<int, unsigned long> > pump_data;
Environment* m_env;
PhysiologyData* m_data;
SESubstanceCompoundInfusion* m_infusion;
public:
static bool command;
//Default Constructor
Pump();
//Overload Constructor
Pump(Environment*, PhysiologyData*);
static void ChangePumpRate(int, unsigned long);
// Device logic will go in here
// This function uses the engine object to query required info
virtual void update(std::unique_ptr<PhysiologyEngine>&);
// Load all pump configurations
virtual void LoadConfig(std::unique_ptr<PhysiologyEngine>&, const char*);
void SetInfusionRate(std::unique_ptr<PhysiologyEngine>&, int);
void Stop();
// Destructor
~Pump();
};
#endif
#ifndef SIMENGINE_H
#define SIMENGINE_H
void Simulation();
void Global_LoadConfig(std::unique_ptr<PhysiologyEngine>&, Config*, const char*, Environment*);
#endif
#ifndef SIMULATIONLOGGER_H
#define SIMULATIONLOGGER_H
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <typeinfo>
#include "PhysiologyData.h"
using namespace std;
class SimulationLogger {
private:
const char* m_filename;
ofstream m_out_file;
public:
SimulationLogger();
//Overload constructor
SimulationLogger(const char*);
void LogData(double, string, string, string, PhysiologyData&);
void LogRate(double, string, string, string, int);
//Destructor
~SimulationLogger();
};
#endif
#include "Controller.h"
//Default constructor
Controller::Controller(): MAX_RATE_Hz(50.0) {
}
// Overloard Constructor
Controller::Controller(Environment* env, PhysiologyData* data) : m_env(env),
m_data(data), MAX_RATE_Hz(50.0) {
srand(time(0)); // seed values using system time
// initialise array from which rates will be picked randomly
array_rate[0] = 200;
array_rate[1] = 250;
array_rate[2] = 300;
array_rate[3] = 150;
}
void Controller::update(std::unique_ptr<PhysiologyEngine>& engine) {
// check controller input rate
if (m_env->time_index % input_period == 0) {
cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout<<"Controller receives data from Monitor at: "<<engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
// Gets data from Monitor
GetData();
m_env->logger->LogData(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RECEIVE",
"Received data from Monitor BP",
patient_state.at(m_env->vector_index-1)
);
// why cant't I compare using patient value
//double p = patient_state.at(m_env->vector_index-1).pressure;
//cout <<p<<endl;
if ( m_env->time_index % 32 == 0/* p < 94.0 doesn't work*/) {
new_rate = array_rate[rand() % 4];
m_env->logger->LogRate(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RATE_CHANGE",
"Controller sends Command to Pump",
new_rate
);
cout<< "Command SENT to PUMP: "<< engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
//Send information to pump (rate, time index)
//Pump::pump_data.push_back(make_pair(200, m_env->time_index));
SetRate(new_rate, m_env->time_index);
//m_env->pump_index++;
}
}
};
void Controller::LoadConfig(std::unique_ptr<PhysiologyEngine>& engine, const char* file_path) {
try
{
// Read configration file
cfg.readFile(file_path);
}
catch(const FileIOException &fioex)
{
std::cerr << "I/O error while reading file." << std::endl;
}
catch(const ParseException &pex)
{
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << std::endl;
}
// Extract the rate and assign it to m_rate_Hz
controller_rate_Hz = cfg.lookup("controller.rate");
Setting& root = cfg.getRoot();
Setting& enabled = root["controller"]["patientData"]["enabled"];
const char* value;
vector<string> p_data;
for (Setting& vital : enabled) {
value = vital;
p_data.push_back(string(value));
}
// Activate patient variables Physiology Data
m_data->HeartRate = (find(p_data.begin(), p_data.end(), "HeartRate") != p_data.end()) ? true : false;
m_data->BloodVolume = (find(p_data.begin(), p_data.end(), "BloodVolume") != p_data.end()) ? true : false;
m_data->BloodPressure = (find(p_data.begin(), p_data.end(), "BloodPressure") != p_data.end()) ? true : false;
time_step = engine->GetTimeStep(TimeUnit::s);
//MAX_RATE_Hz = 1/time_step;
// integer input rate for controller
input_period = (1/controller_rate_Hz) / time_step;
is_input_multiple = fmod(MAX_RATE_Hz, controller_rate_Hz) == 0.0;
if(controller_rate_Hz > MAX_RATE_Hz) {
cout <<"\nController rate is greater than MAX: 50.0\n\n";
Stop();
}
else if(!is_input_multiple) {
cout <<"\nController rate is not a multiple of MAX: 50.0\n\n";
Stop();
}
}
void Controller::SendValues(PhysiologyData& data) {
//patient_state.emplace_back(value);
patient_state.push_back(data);
}
void Controller::GetData() {
// The following are activated in the config file if controller
// requires them and set to NaN if not required
cout<<"CONTROLLER DATA\n";
if (m_data->HeartRate){
cout<< "Heart Rate: "<<patient_state.at(m_env->
vector_index-1).heart_rate<<endl;
}
else {
patient_state.at(m_env->
vector_index-1).heart_rate=numeric_limits<double>::quiet_NaN();
}
if (m_data->BloodPressure) {
cout<< "Pressure: "<<patient_state.at(m_env->
vector_index-1).pressure<<endl;
}
else {
patient_state.at(m_env->
vector_index-1).pressure=numeric_limits<double>::quiet_NaN();
}
if (m_data->BloodVolume) {
cout<< "Blood Volume: "<<patient_state.at(m_env->
vector_index-1).blood_volume<<endl;
}
else {
patient_state.at(m_env->
vector_index-1).blood_volume=numeric_limits<double>::quiet_NaN();
}
cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
}
// initialise static variable
vector<PhysiologyData> Controller::patient_state;
//const int Controller::array_sz = 4;
void Controller::Stop() {
throw "Error";
}
void Controller::SetRate(int rate, unsigned int time_index) {
Pump::ChangePumpRate(rate, m_env->time_index );
}
// Destructor
Controller::~Controller() {
// clear container when done
patient_state.clear();
}
#include "MedicalDevice.h"
// Constructor
MedicalDevice::MedicalDevice() :
m_rate_Hz(50.0), MAX_RATE_Hz(50.0) // Initialize member variables
{
};
// Use rate provided in config file; Default is 1 from Constructor initialization
// Engine object will be utilized here to query data