Merge remote-tracking branch 'git/feature/major-organ-systems'

This commit is contained in:
2025-08-19 17:58:09 -07:00
32 changed files with 961 additions and 74 deletions
+18 -1
View File
@@ -5,7 +5,24 @@ cmake_minimum_required(VERSION 3.10)
project(MedicalLib) project(MedicalLib)
# Add the library # Add the library
add_library(MedicalLib SHARED src/MedicalLib.cpp src/Patient.cpp) add_library(MedicalLib SHARED
src/MedicalLib.cpp
src/Patient.cpp
src/Organ.cpp
src/Heart.cpp
src/Lungs.cpp
src/Brain.cpp
src/Liver.cpp
src/Kidneys.cpp
src/Bladder.cpp
src/Stomach.cpp
src/Intestines.cpp
src/Gallbladder.cpp
src/Pancreas.cpp
src/Esophagus.cpp
src/Spleen.cpp
src/SpinalCord.cpp
)
# Define MEDICAL_LIB_EXPORT, so that __declspec(dllexport) is used # Define MEDICAL_LIB_EXPORT, so that __declspec(dllexport) is used
target_compile_definitions(MedicalLib PRIVATE MEDICAL_LIB_EXPORT) target_compile_definitions(MedicalLib PRIVATE MEDICAL_LIB_EXPORT)
+34 -11
View File
@@ -1,28 +1,51 @@
#include <iostream> #include <iostream>
#include <memory>
#include "MedicalLib/MedicalLib.h" #include "MedicalLib/MedicalLib.h"
#include "MedicalLib/Patient.h"
#include "MedicalLib/Organ.h"
#include "MedicalLib/Heart.h"
#include "MedicalLib/Lungs.h"
#include "MedicalLib/Brain.h"
#include "MedicalLib/Liver.h"
#include "MedicalLib/Kidneys.h"
#include "MedicalLib/Stomach.h"
void printPatientVitals(const Patient& patient) { void printPatientSummary(const Patient& patient) {
std::cout << "Patient ID: " << patient.patientId << std::endl; std::cout << "--- Patient Summary (ID: " << patient.patientId << ") ---" << std::endl;
std::cout << " Blood Pressure: " << patient.bloodPressureSystolic << "/" << patient.bloodPressureDiastolic << " mmHg" << std::endl; for (const auto& organ_ptr : patient.organs) {
std::cout << " Heart Rate: " << patient.heartRate << " bpm" << std::endl; // Print the general summary for each organ
std::cout << " Respiration Rate: " << patient.respirationRate << " breaths/min" << std::endl; std::cout << organ_ptr->getSummary() << std::endl;
std::cout << " Body Temperature: " << patient.bodyTemperature << " C" << std::endl;
std::cout << " Oxygen Saturation: " << patient.oxygenSaturation << " %" << std::endl; // Example of accessing specialized properties using dynamic_cast
if (const Heart* heart = dynamic_cast<const Heart*>(organ_ptr.get())) {
std::cout << " -> Specific: Patient Heart Rate is " << heart->getHeartRate() << " bpm." << std::endl;
}
if (const Lungs* lungs = dynamic_cast<const Lungs*>(organ_ptr.get())) {
std::cout << " -> Specific: Patient SpO2 is " << lungs->getOxygenSaturation() << "%." << std::endl;
}
if (const Kidneys* kidneys = dynamic_cast<const Kidneys*>(organ_ptr.get())) {
std::cout << " -> Specific: Kidney Filtration Rate is " << kidneys->getFiltrationRate() << " ml/min." << std::endl;
}
if (const Stomach* stomach = dynamic_cast<const Stomach*>(organ_ptr.get())) {
std::cout << " -> Specific: Stomach pH is " << stomach->getPhLevel() << "." << std::endl;
}
}
std::cout << "------------------------------------" << std::endl;
} }
int main() { int main() {
// Initialize a new patient // Initialize a new patient
Patient patient = initializePatient(1); Patient patient = initializePatient(1);
std::cout << "Initial Vitals:" << std::endl; std::cout << "Initial State:" << std::endl;
printPatientVitals(patient); printPatientSummary(patient);
// Simulate a time step // Simulate a time step
double deltaTime_s = 1.0; double deltaTime_s = 1.0;
updatePatient(patient, deltaTime_s); updatePatient(patient, deltaTime_s);
std::cout << "\nVitals after " << deltaTime_s << " second(s):" << std::endl; std::cout << "\nState after " << deltaTime_s << " second(s):" << std::endl;
printPatientVitals(patient); printPatientSummary(patient);
return 0; return 0;
} }
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Bladder.
*/
class MEDICAL_LIB_API Bladder : public Organ {
public:
Bladder(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
// Note: A real model would get urine input from kidneys.
// For now, it will just fill at a constant rate.
void addUrine(double amount_ml);
double getCurrentVolume() const;
double getCapacity() const;
private:
double currentVolume; // in ml
double capacity; // in ml
};
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Brain organ.
*/
class MEDICAL_LIB_API Brain : public Organ {
public:
/**
* @brief Constructor for the Brain class.
* @param id The ID of the organ.
*/
Brain(int id);
/**
* @brief Updates the brain's state over time.
* @param deltaTime_s The time elapsed in seconds.
*/
void update(double deltaTime_s) override;
/**
* @brief Gets a string summary of the brain's vitals.
* @return A string containing the brain's vital signs.
*/
std::string getSummary() const override;
// Specific getters for Brain properties
double getConsciousnessLevel() const; // A simplified scale, e.g., 0.0 to 1.0
double getCerebralBloodFlow() const; // in ml/100g/min
private:
double consciousnessLevel;
double cerebralBloodFlow;
};
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Esophagus.
* @note This is a placeholder with minimal logic for now.
*/
class MEDICAL_LIB_API Esophagus : public Organ {
public:
Esophagus(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getMotility() const; // Peristalsis efficiency
private:
double motility;
};
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Gallbladder.
*/
class MEDICAL_LIB_API Gallbladder : public Organ {
public:
Gallbladder(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getBileStored() const;
private:
double bileStored; // in ml
};
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Heart organ.
*/
class MEDICAL_LIB_API Heart : public Organ {
public:
/**
* @brief Constructor for the Heart class.
* @param id The ID of the organ.
*/
Heart(int id);
/**
* @brief Updates the heart's state over time.
* @param deltaTime_s The time elapsed in seconds.
*/
void update(double deltaTime_s) override;
/**
* @brief Gets a string summary of the heart's vitals.
* @return A string containing the heart's vital signs.
*/
std::string getSummary() const override;
// Specific getters for Heart properties
double getHeartRate() const;
double getBloodPressureSystolic() const;
double getBloodPressureDiastolic() const;
private:
double heartRate;
double bloodPressureSystolic;
double bloodPressureDiastolic;
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Intestines (Small and Large combined).
*/
class MEDICAL_LIB_API Intestines : public Organ {
public:
Intestines(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getNutrientAbsorptionRate() const;
double getWaterAbsorptionRate() const;
private:
double nutrientAbsorptionRate; // in arbitrary units
double waterAbsorptionRate; // in ml/s
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Kidneys.
*/
class MEDICAL_LIB_API Kidneys : public Organ {
public:
Kidneys(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getFiltrationRate() const;
double getUrineProductionRate() const;
private:
double filtrationRate; // in ml/min
double urineProductionRate; // in ml/s
};
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Liver organ.
*/
class MEDICAL_LIB_API Liver : public Organ {
public:
/**
* @brief Constructor for the Liver class.
* @param id The ID of the organ.
*/
Liver(int id);
/**
* @brief Updates the liver's state over time.
* @param deltaTime_s The time elapsed in seconds.
*/
void update(double deltaTime_s) override;
/**
* @brief Gets a string summary of the liver's vitals.
* @return A string containing the liver's vital signs.
*/
std::string getSummary() const override;
// Specific getters for Liver properties
double getBileProductionRate() const; // in ml/s
double getGlucoseProductionRate() const; // in g/s
private:
double bileProductionRate;
double glucoseProductionRate;
};
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Lungs organ.
*/
class MEDICAL_LIB_API Lungs : public Organ {
public:
/**
* @brief Constructor for the Lungs class.
* @param id The ID of the organ.
*/
Lungs(int id);
/**
* @brief Updates the lungs' state over time.
* @param deltaTime_s The time elapsed in seconds.
*/
void update(double deltaTime_s) override;
/**
* @brief Gets a string summary of the lungs' vitals.
* @return A string containing the lungs' vital signs.
*/
std::string getSummary() const override;
// Specific getters for Lungs properties
double getRespirationRate() const;
double getOxygenSaturation() const;
private:
double respirationRate;
double oxygenSaturation;
};
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <string>
#include <vector>
// Define MEDICAL_LIB_EXPORT for exporting symbols from the DLL
#if defined(_WIN32)
#if defined(MEDICAL_LIB_EXPORT)
#define MEDICAL_LIB_API __declspec(dllexport)
#else
#define MEDICAL_LIB_API __declspec(dllimport)
#endif
#else
#define MEDICAL_LIB_API
#endif
/**
* @brief Abstract base class for all organ types.
*/
class MEDICAL_LIB_API Organ {
public:
/**
* @brief Constructor for the Organ class.
* @param id The ID of the organ.
* @param type The type of the organ as a string.
*/
Organ(int id, const std::string& type);
/**
* @brief Virtual destructor.
*/
virtual ~Organ() = default;
/**
* @brief Pure virtual function to update the organ's state over time.
* @param deltaTime_s The time elapsed in seconds.
*/
virtual void update(double deltaTime_s) = 0;
/**
* @brief Pure virtual function to get a string summary of the organ's vitals.
* @return A string containing the organ's vital signs.
*/
virtual std::string getSummary() const = 0;
/**
* @brief Gets the organ ID.
* @return The organ ID.
*/
int getId() const;
/**
* @brief Gets the organ type.
* @return The organ type as a string.
*/
const std::string& getType() const;
protected:
int organId;
std::string organType;
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Pancreas, with both endocrine and exocrine functions.
*/
class MEDICAL_LIB_API Pancreas : public Organ {
public:
Pancreas(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getInsulinProduction() const;
double getGlucagonProduction() const;
private:
double insulinProduction; // in units/hr
double glucagonProduction; // in ng/hr
};
+7 -6
View File
@@ -1,16 +1,17 @@
#pragma once #pragma once
#include <vector>
#include <memory>
// Forward-declare the Organ class to avoid circular dependencies
class Organ;
/** /**
* @brief Holds all the vital signs and other medical information for a patient. * @brief Holds all the vital signs and other medical information for a patient.
*/ */
struct Patient { struct Patient {
int patientId; int patientId;
double bloodPressureSystolic; std::vector<std::unique_ptr<Organ>> organs;
double bloodPressureDiastolic;
double heartRate;
double respirationRate;
double bodyTemperature;
double oxygenSaturation;
}; };
// Define MEDICAL_LIB_EXPORT for exporting symbols from the DLL // Define MEDICAL_LIB_EXPORT for exporting symbols from the DLL
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Spinal Cord.
*/
class MEDICAL_LIB_API SpinalCord : public Organ {
public:
SpinalCord(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getSignalConductionVelocity() const; // in m/s
private:
double signalConductionVelocity;
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Spleen.
*/
class MEDICAL_LIB_API Spleen : public Organ {
public:
Spleen(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getRedBloodCellCount() const;
double getWhiteBloodCellCount() const;
private:
double redBloodCellCount; // in millions/uL
double whiteBloodCellCount; // in thousands/uL
};
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Organ.h"
/**
* @brief Represents the Stomach.
*/
class MEDICAL_LIB_API Stomach : public Organ {
public:
Stomach(int id);
void update(double deltaTime_s) override;
std::string getSummary() const override;
double getPhLevel() const;
double getDigestionRate() const;
private:
double phLevel; // Acidity
double digestionRate; // in arbitrary units
};
+29
View File
@@ -0,0 +1,29 @@
#include "MedicalLib/Bladder.h"
#include <random>
#include <algorithm>
#include <sstream>
Bladder::Bladder(int id) : Organ(id, "Bladder"), currentVolume(50.0), capacity(500.0) {}
void Bladder::update(double deltaTime_s) {
// In a more complex model, this would be driven by kidney output.
// For now, simulate a constant fill rate.
const double fillRate_ml_per_s = 0.02;
currentVolume += fillRate_ml_per_s * deltaTime_s;
currentVolume = std::clamp(currentVolume, 0.0, capacity);
}
void Bladder::addUrine(double amount_ml) {
currentVolume += amount_ml;
currentVolume = std::clamp(currentVolume, 0.0, capacity);
}
std::string Bladder::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Volume: " << currentVolume << " / " << capacity << " ml";
return ss.str();
}
double Bladder::getCurrentVolume() const { return currentVolume; }
double Bladder::getCapacity() const { return capacity; }
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Brain.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Brain::Brain(int id) : Organ(id, "Brain"), consciousnessLevel(1.0), cerebralBloodFlow(50.0) {}
void Brain::update(double deltaTime_s) {
const double baseline_consciousness = 1.0;
const double baseline_cbf = 50.0;
const double theta = 0.05; // Slower reversion for brain metrics
const double consciousness_stddev = 0.001;
const double cbf_stddev = 0.5;
consciousnessLevel += theta * (baseline_consciousness - consciousnessLevel) * deltaTime_s + getFluctuation(consciousness_stddev * deltaTime_s);
cerebralBloodFlow += theta * (baseline_cbf - cerebralBloodFlow) * deltaTime_s + getFluctuation(cbf_stddev * deltaTime_s);
consciousnessLevel = std::clamp(consciousnessLevel, 0.0, 1.0);
cerebralBloodFlow = std::clamp(cerebralBloodFlow, 40.0, 60.0);
}
std::string Brain::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Consciousness Level: " << consciousnessLevel * 100 << "%\n"
<< " Cerebral Blood Flow: " << cerebralBloodFlow << " ml/100g/min";
return ss.str();
}
double Brain::getConsciousnessLevel() const { return consciousnessLevel; }
double Brain::getCerebralBloodFlow() const { return cerebralBloodFlow; }
+26
View File
@@ -0,0 +1,26 @@
#include "MedicalLib/Esophagus.h"
#include <random>
#include <algorithm>
#include <sstream>
Esophagus::Esophagus(int id) : Organ(id, "Esophagus"), motility(1.0) {}
void Esophagus::update(double deltaTime_s) {
// Placeholder, no real logic yet.
// Fluctuate motility slightly.
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, 0.001);
motility += d(gen) * deltaTime_s;
motility = std::clamp(motility, 0.95, 1.05);
}
std::string Esophagus::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Motility: " << motility * 100 << "%";
return ss.str();
}
double Esophagus::getMotility() const { return motility; }
+26
View File
@@ -0,0 +1,26 @@
#include "MedicalLib/Gallbladder.h"
#include <random>
#include <algorithm>
#include <sstream>
Gallbladder::Gallbladder(int id) : Organ(id, "Gallbladder"), bileStored(30.0) {}
void Gallbladder::update(double deltaTime_s) {
// A real model would be affected by liver production and digestion.
// For now, it just sits there with a small fluctuation.
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, 0.01);
bileStored += d(gen) * deltaTime_s;
bileStored = std::clamp(bileStored, 10.0, 50.0);
}
std::string Gallbladder::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Bile Stored: " << bileStored << " ml";
return ss.str();
}
double Gallbladder::getBileStored() const { return bileStored; }
+43
View File
@@ -0,0 +1,43 @@
#include "MedicalLib/Heart.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Heart::Heart(int id) : Organ(id, "Heart"), heartRate(75.0), bloodPressureSystolic(120.0), bloodPressureDiastolic(80.0) {}
void Heart::update(double deltaTime_s) {
const double baseline_hr = 75.0;
const double baseline_bp_systolic = 120.0;
const double baseline_bp_diastolic = 80.0;
const double theta = 0.1; // Mean reversion speed
const double hr_stddev = 0.1;
const double bp_stddev = 0.1;
heartRate += theta * (baseline_hr - heartRate) * deltaTime_s + getFluctuation(hr_stddev * deltaTime_s);
bloodPressureSystolic += theta * (baseline_bp_systolic - bloodPressureSystolic) * deltaTime_s + getFluctuation(bp_stddev * deltaTime_s);
bloodPressureDiastolic += theta * (baseline_bp_diastolic - bloodPressureDiastolic) * deltaTime_s + getFluctuation(bp_stddev * deltaTime_s);
heartRate = std::clamp(heartRate, 60.0, 100.0);
bloodPressureSystolic = std::clamp(bloodPressureSystolic, 90.0, 120.0);
bloodPressureDiastolic = std::clamp(bloodPressureDiastolic, 60.0, 80.0);
}
std::string Heart::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Heart Rate: " << heartRate << " bpm\n"
<< " Blood Pressure: " << bloodPressureSystolic << "/" << bloodPressureDiastolic << " mmHg";
return ss.str();
}
double Heart::getHeartRate() const { return heartRate; }
double Heart::getBloodPressureSystolic() const { return bloodPressureSystolic; }
double Heart::getBloodPressureDiastolic() const { return bloodPressureDiastolic; }
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Intestines.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Intestines::Intestines(int id) : Organ(id, "Intestines"), nutrientAbsorptionRate(1.0), waterAbsorptionRate(0.1) {}
void Intestines::update(double deltaTime_s) {
const double baseline_nutrient_abs = 1.0;
const double baseline_water_abs = 0.1;
const double theta = 0.05;
const double nutrient_abs_stddev = 0.02;
const double water_abs_stddev = 0.005;
nutrientAbsorptionRate += theta * (baseline_nutrient_abs - nutrientAbsorptionRate) * deltaTime_s + getFluctuation(nutrient_abs_stddev * deltaTime_s);
waterAbsorptionRate += theta * (baseline_water_abs - waterAbsorptionRate) * deltaTime_s + getFluctuation(water_abs_stddev * deltaTime_s);
nutrientAbsorptionRate = std::clamp(nutrientAbsorptionRate, 0.8, 1.2);
waterAbsorptionRate = std::clamp(waterAbsorptionRate, 0.08, 0.12);
}
std::string Intestines::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Nutrient Absorption: " << nutrientAbsorptionRate << "\n"
<< " Water Absorption: " << waterAbsorptionRate << " ml/s";
return ss.str();
}
double Intestines::getNutrientAbsorptionRate() const { return nutrientAbsorptionRate; }
double Intestines::getWaterAbsorptionRate() const { return waterAbsorptionRate; }
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Kidneys.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Kidneys::Kidneys(int id) : Organ(id, "Kidneys"), filtrationRate(125.0), urineProductionRate(0.02) {}
void Kidneys::update(double deltaTime_s) {
const double baseline_filtration = 125.0;
const double baseline_urine_prod = 0.02;
const double theta = 0.03;
const double filtration_stddev = 1.0;
const double urine_prod_stddev = 0.001;
filtrationRate += theta * (baseline_filtration - filtrationRate) * deltaTime_s + getFluctuation(filtration_stddev * deltaTime_s);
urineProductionRate += theta * (baseline_urine_prod - urineProductionRate) * deltaTime_s + getFluctuation(urine_prod_stddev * deltaTime_s);
filtrationRate = std::clamp(filtrationRate, 100.0, 150.0);
urineProductionRate = std::clamp(urineProductionRate, 0.01, 0.03);
}
std::string Kidneys::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Filtration Rate: " << filtrationRate << " ml/min\n"
<< " Urine Production: " << urineProductionRate << " ml/s";
return ss.str();
}
double Kidneys::getFiltrationRate() const { return filtrationRate; }
double Kidneys::getUrineProductionRate() const { return urineProductionRate; }
+42
View File
@@ -0,0 +1,42 @@
#include "MedicalLib/Liver.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
// Healthy baseline rates converted to per-second
// Bile: 400-800 ml/day -> ~0.0069 ml/s
// Glucose: ~90 g/day -> ~0.001 g/s
Liver::Liver(int id) : Organ(id, "Liver"), bileProductionRate(0.0069), glucoseProductionRate(0.001) {}
void Liver::update(double deltaTime_s) {
const double baseline_bile_rate = 0.0069;
const double baseline_glucose_rate = 0.001;
const double theta = 0.02; // Slow reversion for metabolic rates
const double bile_stddev = 0.0001;
const double glucose_stddev = 0.00005;
bileProductionRate += theta * (baseline_bile_rate - bileProductionRate) * deltaTime_s + getFluctuation(bile_stddev * deltaTime_s);
glucoseProductionRate += theta * (baseline_glucose_rate - glucoseProductionRate) * deltaTime_s + getFluctuation(glucose_stddev * deltaTime_s);
bileProductionRate = std::clamp(bileProductionRate, 0.005, 0.009);
glucoseProductionRate = std::clamp(glucoseProductionRate, 0.0008, 0.0012);
}
std::string Liver::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Bile Production Rate: " << bileProductionRate * 60 << " ml/min\n"
<< " Glucose Production Rate: " << glucoseProductionRate * 60 << " g/min";
return ss.str();
}
double Liver::getBileProductionRate() const { return bileProductionRate; }
double Liver::getGlucoseProductionRate() const { return glucoseProductionRate; }
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Lungs.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Lungs::Lungs(int id) : Organ(id, "Lungs"), respirationRate(16.0), oxygenSaturation(98.0) {}
void Lungs::update(double deltaTime_s) {
const double baseline_rr = 16.0;
const double baseline_spo2 = 98.0;
const double theta = 0.1; // Mean reversion speed
const double rr_stddev = 0.05;
const double spo2_stddev = 0.02;
respirationRate += theta * (baseline_rr - respirationRate) * deltaTime_s + getFluctuation(rr_stddev * deltaTime_s);
oxygenSaturation += theta * (baseline_spo2 - oxygenSaturation) * deltaTime_s + getFluctuation(spo2_stddev * deltaTime_s);
respirationRate = std::clamp(respirationRate, 12.0, 20.0);
oxygenSaturation = std::clamp(oxygenSaturation, 96.0, 100.0);
}
std::string Lungs::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Respiration Rate: " << respirationRate << " breaths/min\n"
<< " Oxygen Saturation: " << oxygenSaturation << " %";
return ss.str();
}
double Lungs::getRespirationRate() const { return respirationRate; }
double Lungs::getOxygenSaturation() const { return oxygenSaturation; }
+11
View File
@@ -0,0 +1,11 @@
#include "MedicalLib/Organ.h"
Organ::Organ(int id, const std::string& type) : organId(id), organType(type) {}
int Organ::getId() const {
return organId;
}
const std::string& Organ::getType() const {
return organType;
}
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Pancreas.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Pancreas::Pancreas(int id) : Organ(id, "Pancreas"), insulinProduction(1.0), glucagonProduction(50.0) {}
void Pancreas::update(double deltaTime_s) {
const double baseline_insulin = 1.0;
const double baseline_glucagon = 50.0;
const double theta = 0.05;
const double insulin_stddev = 0.01;
const double glucagon_stddev = 1.0;
insulinProduction += theta * (baseline_insulin - insulinProduction) * deltaTime_s + getFluctuation(insulin_stddev * deltaTime_s);
glucagonProduction += theta * (baseline_glucagon - glucagonProduction) * deltaTime_s + getFluctuation(glucagon_stddev * deltaTime_s);
insulinProduction = std::clamp(insulinProduction, 0.5, 2.0);
glucagonProduction = std::clamp(glucagonProduction, 40.0, 60.0);
}
std::string Pancreas::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Insulin Production: " << insulinProduction << " units/hr\n"
<< " Glucagon Production: " << glucagonProduction << " ng/hr";
return ss.str();
}
double Pancreas::getInsulinProduction() const { return insulinProduction; }
double Pancreas::getGlucagonProduction() const { return glucagonProduction; }
+36 -56
View File
@@ -1,74 +1,54 @@
#include "MedicalLib/Patient.h" #include "MedicalLib/Patient.h"
#include <random> #include "MedicalLib/Heart.h"
#include <algorithm> // For std::clamp #include "MedicalLib/Lungs.h"
#include "MedicalLib/Brain.h"
#include "MedicalLib/Liver.h"
#include "MedicalLib/Kidneys.h"
#include "MedicalLib/Bladder.h"
#include "MedicalLib/Stomach.h"
#include "MedicalLib/Intestines.h"
#include "MedicalLib/Gallbladder.h"
#include "MedicalLib/Pancreas.h"
#include "MedicalLib/Esophagus.h"
#include "MedicalLib/Spleen.h"
#include "MedicalLib/SpinalCord.h"
#include <memory>
/** /**
* @brief Helper function to generate random fluctuations from a normal distribution. * @brief Initializes a new patient with baseline vital signs and a standard set of organs.
* @param stddev The standard deviation of the distribution.
* @return A random value.
*/
double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
/**
* @brief Initializes a new patient with baseline vital signs.
* @param patientId The ID for the new patient. * @param patientId The ID for the new patient.
* @return A Patient struct with default healthy values. * @return A Patient struct with default healthy values.
*/ */
Patient initializePatient(int patientId) { Patient initializePatient(int patientId) {
Patient patient; Patient patient;
patient.patientId = patientId; patient.patientId = patientId;
patient.bloodPressureSystolic = 120.0;
patient.bloodPressureDiastolic = 80.0; // Initialize default organs
patient.heartRate = 75.0; patient.organs.push_back(std::make_unique<Heart>(1));
patient.respirationRate = 16.0; patient.organs.push_back(std::make_unique<Lungs>(2));
patient.bodyTemperature = 37.0; patient.organs.push_back(std::make_unique<Brain>(3));
patient.oxygenSaturation = 98.0; patient.organs.push_back(std::make_unique<Liver>(4));
patient.organs.push_back(std::make_unique<Kidneys>(5));
patient.organs.push_back(std::make_unique<Bladder>(6));
patient.organs.push_back(std::make_unique<Stomach>(7));
patient.organs.push_back(std::make_unique<Intestines>(8));
patient.organs.push_back(std::make_unique<Gallbladder>(9));
patient.organs.push_back(std::make_unique<Pancreas>(10));
patient.organs.push_back(std::make_unique<Esophagus>(11));
patient.organs.push_back(std::make_unique<Spleen>(12));
patient.organs.push_back(std::make_unique<SpinalCord>(13));
return patient; return patient;
} }
/** /**
* @brief Updates the patient's vital signs based on the time elapsed. * @brief Updates the patient's state by updating the state of all their organs.
* This function simulates minor, random fluctuations around a healthy baseline.
* @param patient The patient to update. * @param patient The patient to update.
* @param deltaTime_s The time elapsed in seconds. * @param deltaTime_s The time elapsed in seconds.
*/ */
void updatePatient(Patient& patient, double deltaTime_s) { void updatePatient(Patient& patient, double deltaTime_s) {
// Baseline healthy values // Update all organs
const double baseline_hr = 75.0; for (auto& organ : patient.organs) {
const double baseline_bp_systolic = 120.0; organ->update(deltaTime_s);
const double baseline_bp_diastolic = 80.0; }
const double baseline_rr = 16.0;
const double baseline_temp = 37.0;
const double baseline_spo2 = 98.0;
// Reversion speed (how quickly vitals return to baseline)
const double theta = 0.1;
// Standard deviations for random fluctuations per second
const double hr_stddev = 0.1;
const double bp_stddev = 0.1;
const double rr_stddev = 0.05;
const double temp_stddev = 0.01;
const double spo2_stddev = 0.02;
// Update vitals using a mean-reverting model
patient.heartRate += theta * (baseline_hr - patient.heartRate) * deltaTime_s + getFluctuation(hr_stddev * deltaTime_s);
patient.bloodPressureSystolic += theta * (baseline_bp_systolic - patient.bloodPressureSystolic) * deltaTime_s + getFluctuation(bp_stddev * deltaTime_s);
patient.bloodPressureDiastolic += theta * (baseline_bp_diastolic - patient.bloodPressureDiastolic) * deltaTime_s + getFluctuation(bp_stddev * deltaTime_s);
patient.respirationRate += theta * (baseline_rr - patient.respirationRate) * deltaTime_s + getFluctuation(rr_stddev * deltaTime_s);
patient.bodyTemperature += theta * (baseline_temp - patient.bodyTemperature) * deltaTime_s + getFluctuation(temp_stddev * deltaTime_s);
patient.oxygenSaturation += theta * (baseline_spo2 - patient.oxygenSaturation) * deltaTime_s + getFluctuation(spo2_stddev * deltaTime_s);
// Clamp values to within healthy physiological ranges
patient.heartRate = std::clamp(patient.heartRate, 60.0, 100.0);
patient.bloodPressureSystolic = std::clamp(patient.bloodPressureSystolic, 90.0, 120.0);
patient.bloodPressureDiastolic = std::clamp(patient.bloodPressureDiastolic, 60.0, 80.0);
patient.respirationRate = std::clamp(patient.respirationRate, 12.0, 20.0);
patient.bodyTemperature = std::clamp(patient.bodyTemperature, 36.5, 37.3);
patient.oxygenSaturation = std::clamp(patient.oxygenSaturation, 96.0, 100.0);
} }
+33
View File
@@ -0,0 +1,33 @@
#include "MedicalLib/SpinalCord.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
SpinalCord::SpinalCord(int id) : Organ(id, "SpinalCord"), signalConductionVelocity(70.0) {}
void SpinalCord::update(double deltaTime_s) {
const double baseline_velocity = 70.0;
const double theta = 0.01;
const double velocity_stddev = 0.1;
signalConductionVelocity += theta * (baseline_velocity - signalConductionVelocity) * deltaTime_s + getFluctuation(velocity_stddev * deltaTime_s);
signalConductionVelocity = std::clamp(signalConductionVelocity, 60.0, 80.0);
}
std::string SpinalCord::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " Signal Velocity: " << signalConductionVelocity << " m/s";
return ss.str();
}
double SpinalCord::getSignalConductionVelocity() const { return signalConductionVelocity; }
+39
View File
@@ -0,0 +1,39 @@
#include "MedicalLib/Spleen.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Spleen::Spleen(int id) : Organ(id, "Spleen"), redBloodCellCount(4.5), whiteBloodCellCount(7.5) {}
void Spleen::update(double deltaTime_s) {
const double baseline_rbc = 4.5;
const double baseline_wbc = 7.5;
const double theta = 0.02;
const double rbc_stddev = 0.01;
const double wbc_stddev = 0.05;
redBloodCellCount += theta * (baseline_rbc - redBloodCellCount) * deltaTime_s + getFluctuation(rbc_stddev * deltaTime_s);
whiteBloodCellCount += theta * (baseline_wbc - whiteBloodCellCount) * deltaTime_s + getFluctuation(wbc_stddev * deltaTime_s);
redBloodCellCount = std::clamp(redBloodCellCount, 4.0, 5.0);
whiteBloodCellCount = std::clamp(whiteBloodCellCount, 5.0, 10.0);
}
std::string Spleen::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " RBC Count: " << redBloodCellCount << " million/uL\n"
<< " WBC Count: " << whiteBloodCellCount << " thousand/uL";
return ss.str();
}
double Spleen::getRedBloodCellCount() const { return redBloodCellCount; }
double Spleen::getWhiteBloodCellCount() const { return whiteBloodCellCount; }
+40
View File
@@ -0,0 +1,40 @@
#include "MedicalLib/Stomach.h"
#include <random>
#include <algorithm>
#include <sstream>
// Helper function for random fluctuations
static double getFluctuation(double stddev) {
static std::random_device rd;
static std::mt19937 gen(rd());
std::normal_distribution<> d(0, stddev);
return d(gen);
}
Stomach::Stomach(int id) : Organ(id, "Stomach"), phLevel(2.0), digestionRate(1.0) {}
void Stomach::update(double deltaTime_s) {
// For now, these values just fluctuate around a baseline.
const double baseline_ph = 2.0;
const double baseline_digestion = 1.0;
const double theta = 0.1;
const double ph_stddev = 0.05;
const double digestion_stddev = 0.02;
phLevel += theta * (baseline_ph - phLevel) * deltaTime_s + getFluctuation(ph_stddev * deltaTime_s);
digestionRate += theta * (baseline_digestion - digestionRate) * deltaTime_s + getFluctuation(digestion_stddev * deltaTime_s);
phLevel = std::clamp(phLevel, 1.5, 3.5);
digestionRate = std::clamp(digestionRate, 0.5, 1.5);
}
std::string Stomach::getSummary() const {
std::stringstream ss;
ss << "Type: " << organType << " (ID: " << organId << ")\n"
<< " pH Level: " << phLevel << "\n"
<< " Digestion Rate: " << digestionRate;
return ss.str();
}
double Stomach::getPhLevel() const { return phLevel; }
double Stomach::getDigestionRate() const { return digestionRate; }