Files
CellSimulation/BaseCellSimulation/Organell.cs
T
2025-11-16 19:52:52 +01:00

570 lines
17 KiB
C#

using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BaseCellSimulation
{
/// <summary>
/// Container, der die aktuellen Ressourcen einer Zelle hält und Hilfsfunktionen bietet.
/// </summary>
public class CellRessources
{
public Resources Res;
public EnviromentState Env = new();
[JsonPropertyName("energy")]
public EnergyPool energyPool;
public Dictionary<string, double> Resources => new Dictionary<string, double>();
public static CellRessources LoadRessources(string jsonPath)
{
string json = File.ReadAllText(jsonPath);
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
var result = new CellRessources();
// deserialice energy
if (root.TryGetProperty("energy", out JsonElement energyElement))
{
result.energyPool = JsonSerializer.Deserialize<EnergyPool>(energyElement.GetRawText());
}
foreach(var property in root.EnumerateObject())
{
if (property.NameEquals("energy"))
continue; // already handled
if (property.Value.ValueKind == JsonValueKind.Number)
{
result.Resources[property.Name] = property.Value.GetDouble();
}
}
return result;
}
public static void SaveRessources(CellRessources ressources, string jsonPath)
{
var options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize(ressources, options);
File.WriteAllText(jsonPath, json);
}
// pH in mM-basiertem Hilfsformat (vereinfachte Umrechnung):
public double pH_in => 3.0 - Math.Log10(Res.Ions.Protons + 1e-12);
public double pH_ext => 3.0 - Math.Log10(Env.Protons + 1e-12);
// --- Hilfsfunktionen (unverändert / kommentiert) ---
public double GetEnergyLevel()
{
double totalATP = Res.Energy.ATP + 0.5 * Res.Energy.ADP + 0.1 * Res.Energy.AMP;
double redoxEnergy = 0.3 * Res.Energy.NADH;
double energy = totalATP + redoxEnergy;
return Math.Clamp(energy / 5.0, 0.0, 1.0);
}
public double EnergyCharge
{
get
{
double atp = Res.Energy.ATP;
double adp = Res.Energy.ADP;
double amp = Res.Energy.AMP;
double total = atp + adp + amp;
if (total < 1e-12) return 0.0;
return (atp + 0.5 * adp) / total;
}
}
public bool IsEnergyDeficient(double threshold = 0.3)
{
return Res.Energy.ATP < threshold;
}
public double GetRedoxRatio()
{
double denominator = Math.Max(Res.Energy.NADH, 1e-9);
return Res.Energy.NAD / denominator;
}
public double GetStressLevel()
{
double stress = Res.Protein.Waste * 0.1 + Res.Ions.ROS * 0.5 + Res.Ions.Protons * 0.05;
return Math.Clamp(stress, 0.0, 1.0);
}
public bool IsUnderStress(double threshold = 0.5)
{
return GetStressLevel() > threshold;
}
public void ConsumeATP(double amount, bool toAMP = false)
{
if (Res.Energy.ATP < amount) amount = Res.Energy.ATP;
Res.Energy.ATP -= amount;
if (toAMP)
{
Res.Energy.AMP += amount;
Res.Phosphate.PPi += amount;
}
else
{
Res.Energy.ADP += amount;
Res.Phosphate.Pi += amount;
}
}
public void RegenerateATP(double amount, bool fromAMP = false)
{
if (fromAMP)
{
if (Res.Energy.AMP < amount) amount = Res.Energy.AMP;
if (Res.Phosphate.Pi < 2 * amount) amount = Res.Phosphate.Pi / 2;
Res.Energy.AMP -= amount;
Res.Phosphate.Pi -= 2 * amount;
}
else
{
if (Res.Energy.ADP < amount) amount = Res.Energy.ADP;
if (Res.Phosphate.Pi < amount) amount = Res.Phosphate.Pi;
Res.Energy.ADP -= amount;
Res.Phosphate.Pi -= amount;
}
Res.Energy.ATP += amount;
}
public void HydrolyzePPi(double amount)
{
if (Res.Phosphate.PPi < amount) amount = Res.Phosphate.PPi;
Res.Phosphate.PPi -= amount;
Res.Phosphate.Pi += 2 * amount;
}
public void TransferNADH(double amount, bool oxidize)
{
if (oxidize)
{
if (Res.Energy.NADH < amount) amount = Res.Energy.NADH;
Res.Energy.NADH -= amount;
Res.Energy.NAD += amount;
}
else
{
if (Res.Energy.NAD < amount) amount = Res.Energy.NAD;
Res.Energy.NAD -= amount;
Res.Energy.NADH += amount;
}
}
public void TransferGTP(double amount, bool toGDP)
{
if (toGDP)
{
if (Res.Energy.GTP < amount) amount = Res.Energy.GTP;
Res.Energy.GTP -= amount;
Res.Energy.GDP += amount;
}
else
{
if (Res.Energy.GDP < amount) amount = Res.Energy.GDP;
Res.Energy.GDP -= amount;
Res.Energy.GTP += amount;
}
}
// --- Initialisierung mit plausiblen Startwerten ---
/// <summary>
/// Erzeugt eine CellRessources-Instanz mit vernünftigen Startwerten (grobe physiologische Annahmen).
/// Alle Werte in mM, falls nicht anders kommentiert.
/// </summary>
public static CellRessources InitDefaults()
{
var cr = new CellRessources();
// Energie-Pool (ATP/ADP/AMP etc.) — typisch: ATP im mm-Bereich
cr.Res.Energy.ATP = 2.5; // mM, Gesamt-ATP (typischer Ruhewert 1-5 mM)
cr.Res.Energy.ADP = 0.5; // mM
cr.Res.Energy.AMP = 0.05; // mM
cr.Res.Energy.NAD = 1.0; // mM (oxidierte Form)
cr.Res.Energy.NADH = 0.1; // mM (reduzierte Form)
cr.Res.Energy.GTP = 0.5; // mM
cr.Res.Energy.GDP = 0.05; // mM
// Phosphate
cr.Res.Phosphate.Pi = 10.0; // mM (anorganisches Phosphat)
cr.Res.Phosphate.PPi = 0.01; // mM (Pyrophosphat, klein)
// Carbon- / Glykolyse-Pool (vereinfachte Startwerte)
cr.Res.Carbon.Glucose = 1.0; // mM intrazellulär (abhängig von Aufnahme)
cr.Res.Carbon.G6P = 0.05;
cr.Res.Carbon.F6P = 0.02;
cr.Res.Carbon.F1_6BP = 0.005;
cr.Res.Carbon.GA3P = 0.01;
cr.Res.Carbon.PBG13 = 0.005;
cr.Res.Carbon.PG3 = 0.02;
cr.Res.Carbon.PG2 = 0.01;
cr.Res.Carbon.PEP = 0.01;
cr.Res.Carbon.Pyruvate = 0.1;
cr.Res.Carbon.Lactate = 1.0;
cr.Res.Carbon.CO2 = 0.1;
cr.Res.Carbon.AcetylCoA = 0.02;
// Proteine & Nukleotid-Pool
cr.Res.Protein.AminoAcids = 5.0; // mM frei verfügbare Aminosäuren
cr.Res.Protein.FunctionalProteins = 100; // arbitrary, relative Konzentration (nicht streng mM)
cr.Res.Protein.Waste = 0.1; // kleiner Startwert
cr.Res.Protein.NucleicAcids = 10.0;
cr.Res.Protein.Nucleotides = 5.0;
cr.Res.Protein.NTP = 2.0;
cr.Res.Protein.dNTP = 0.05;
cr.Res.Protein.mRNA = 0.01;
cr.Res.Protein.DNA_damage = 0.0;
cr.Res.Protein.AcetylCoA = 0.02;
cr.Res.Protein.SAM = 0.1;
cr.Res.Protein.MET = 0.1;
cr.Res.Protein.SAH = 0.01;
cr.Res.Protein.Homocystein = 0.01;
cr.Res.Protein.Adenosin = 0.1;
cr.Res.Protein.tRNA = 0.05;
cr.Res.Protein.Aminoacyl_tRNA = 0.02;
// Ionen
cr.Res.Ions.Protons = 0.0001; // mM -> entspricht ~pH7 (vereinfachte Umrechnung)
cr.Res.Ions.ROS = 0.001; // kleine ROS-Basislast
cr.Res.Ions.Na = 10.0; // Intrazelluläres Na+ ~ 5-15 mM (Zelltypabhängig)
cr.Res.Ions.K = 140.0; // Intrazelluläres K+ ~ 140 mM
cr.Res.Ions.H2O2 = 0.0001;
// Cofaktoren / Folate
cr.Res.Cofactor.B12 = 1e-6;
cr.Res.Folate.THF = 0.01;
cr.Res.Folate.MethylTHF = 0.005;
// Zellkern-Ressourcen (vereinfachte Defaults)
cr.Res.Nucleus.ChromatinAccessibility = 0.5;
cr.Res.Nucleus.ReplicationProgress = 0.0;
// Calcium-Zustand (CellCaState hat sinnvolle Defaultwerte)
cr.Res.Ca = new CellCaState()
{
CytosolicCa = 0.0001, // 100 nM -> 0.0001 mM
ER_Ca = 0.5,
LeakK = 0.001,
SERCA_Vmax = 0.01,
SERCA_Km = 0.0002,
SERCA_ATP_per_twoCa = 1.0,
LysosomeActivity = 0.1
};
// Sonstige Ressourcen
cr.Res.Oxygen = 0.2; // mM Lösungssauerstoff (abhängig von Umgebung)
cr.Res.Heat = 0.0;
cr.Res.Lipids = 10.0;
cr.Res.PhosphorylatedSubstrates = 1.0;
// Umgebung / Extrazellulärwerte
cr.Env.Glucose = 5.0; // Blutglukose ~5 mM
cr.Env.Oxygen = 0.2; // mM
cr.Env.Waste = 0.0;
cr.Env.Lactate = 1.0;
cr.Env.Insulin = 0.0;
cr.Env.Protons = 0.0001; // ähnlich pH 7
cr.Env.Na = 140.0; // extrazelluläres Na+ ~ 140 mM
cr.Env.K = 4.0; // extrazelluläres K+ ~ 4-5 mM
cr.Env.Ca = 1.2; // extrazelluläres Ca2+ ~1.1-1.3 mM
return cr;
}
}
// ------------------------------------------------------------
// Datendefinitionen (geordnet und kommentiert)
// ------------------------------------------------------------
/// <summary>Energiemengen: ATP/ADP/AMP + NAD/NADH + GTP/GDP</summary>
public struct EnergyPool
{
/// <summary>
/// Adenosine-triphosphate
/// </summary>
public double ATP;
/// <summary>
/// Adenosine diphosphate
/// </summary>
public double ADP;
/// <summary>
/// Adenosine monophosphat
/// </summary>
public double AMP;
/// <summary>
/// Nicotinamide adenine dinucleotide
/// </summary>
public double NAD;
/// <summary>
/// Nicotinamide adenine dinucleotide
/// </summary>
public double NADH;
/// <summary>
/// Nicotinamide adenine dinucleotide phosphate
/// </summary>
public double NADPH;
/// <summary>
/// Guanosintriphosphat
/// </summary>
public double GTP;
/// <summary>
/// Guanosindiphosphat
/// </summary>
public double GDP;
/// <summary>
/// inorganic phosphate
/// </summary>
public double Pi;
/// <summary>
/// Pyrophosphat
/// </summary>
public double PPi;
}
/// <summary>Inorganische Phosphate</summary>
public struct Phosphate
{
/// <summary>
/// inorganic phosphate
/// </summary>
public double Pi;
/// <summary>
/// Pyrophosphat
/// </summary>
public double PPi;
}
/// <summary>Kohlenstoff- / Glykolyse-Intermediaten</summary>
public struct CarbonPool
{
public double Glucose;
/// <summary>
/// Glucose-6-phosphate
/// </summary>
public double G6P;
/// <summary>
/// Fructose-6-phosphate
/// </summary>
public double F6P;
/// <summary>
/// Fructose 1,6-bisphosphate
/// </summary>
public double F1_6BP;
/// <summary>
/// Glycerinaldehyd-3-phosphat
/// </summary>
public double GA3P;
/// <summary>
/// 1,3-Bisphosphoglycerat
/// </summary>
public double PBG13;
/// <summary>
/// 3-Phosphoglycerat
/// </summary>
public double PG3;
/// <summary>
/// 2-Phosphoglycerat
/// </summary>
public double PG2;
/// <summary>
/// Phosphoenolpyruvat
/// </summary>
public double PEP;
public double Pyruvate;
public double Lactate;
public double CO2;
public double AcetylCoA;
}
/// <summary>Proteine, Nukleotide, mRNA, etc.</summary>
public struct ProteinPool
{
public double AminoAcids;
public double FunctionalProteins;
public double Waste;
public double NucleicAcids;
public double Nucleotides;
/// <summary>
/// Nukleosidtriphosphate
/// </summary>
public double NTP;
/// <summary>
/// Desoxyribonukleotidtriphosphate
/// </summary>
public double dNTP;
public double mRNA;
public double DNA_damage;
public double AcetylCoA;
/// <summary>
/// S-Adenosylmethionin
/// </summary>
public double SAM;
/// <summary>
/// Methionine
/// </summary>
public double MET;
/// <summary>
/// S-Adenosylhomocystein
/// </summary>
public double SAH;
public double Homocystein;
public double Adenosin;
internal double tRNA;
internal double Aminoacyl_tRNA;
}
/// <summary>Ionen und kleine Signalmoleküle</summary>
public struct IonPool
{
public double Protons; // H+ (vereinfachte Einheit mM)
/// <summary>
/// reactive oxygen species
/// </summary>
public double ROS;
/// <summary>
/// NAtrium-Ionen
/// </summary>
public double Na;
/// <summary>
/// Kalium-Ionen
/// </summary>
public double K;
public double H2O2;
}
public struct Cofactor
{
public double B12;
}
public struct Folates
{
/// <summary>
/// Tetrahydrofolsäure
/// </summary>
public double THF { get; internal set; }
public double MethylTHF { get; internal set; }
}
public struct NucleusRessources
{
public double ChromatinAccessibility;
public double ReplicationProgress;
}
/// <summary>Gesammelte Ressourcen einer Zelle</summary>
public struct Resources
{
public EnergyPool Energy;
public Phosphate Phosphate;
public CarbonPool Carbon;
public ProteinPool Protein;
public IonPool Ions;
public CellCaState Ca;
public NucleusRessources Nucleus;
public Cofactor Cofactor;
public Folates Folate;
public double Oxygen;
public double Heat;
public double Lipids;
public double PhosphorylatedSubstrates;
}
public enum CellState { Resting, Dividing, Apoptosis }
public enum CAToxicity { None, Mild, Severe, Lethal }
public class EnviromentState
{
public double Glucose;
public double Oxygen;
public double Waste;
public double Lactate;
public double Insulin;
public double Protons;
public double Na;
public double K;
public double Ca;
}
/// <summary>
/// Ein einfaches Modell des zellulären Calcium-Haushalts.
/// Werte in mM; Defaultwerte sind phänotypisch realistisch gewählt.
/// </summary>
public struct CellCaState
{
public double CytosolicCa { get; set; } // zytosolisches Ca (mM), üblich ~100 nM = 0.0001 mM
public double ER_Ca { get; set; } // ER Calcium (mM)
public double LeakK { get; set; } // Leck-Koeffizient
public double SERCA_Vmax { get; set; }
public double SERCA_Km { get; set; } // Km in mM
public double SERCA_ATP_per_twoCa { get; set; }
public double LysosomeActivity { get; internal set; }
public const double ToxicityThresholdMild = 0.001; // 1 µM
public const double ToxicityThresholdSevere = 0.01; // 10 µM
public const double ToxicityThresholdLethal = 0.1; // 100 µM
public CellCaState()
{
CytosolicCa = 0.0001;
ER_Ca = 0.5;
LeakK = 0.001;
SERCA_Vmax = 0.01;
SERCA_Km = 0.0002;
SERCA_ATP_per_twoCa = 1.0;
LysosomeActivity = 0.1;
}
public CAToxicity getCaToxicityLevel()
{
if (CytosolicCa >= ToxicityThresholdLethal) return CAToxicity.Lethal;
else if (CytosolicCa >= ToxicityThresholdSevere) return CAToxicity.Severe;
else if (CytosolicCa >= ToxicityThresholdMild) return CAToxicity.Mild;
else return CAToxicity.None;
}
}
public interface Organell
{
void applyChanges(CellRessources Resources, double dt);
void calculateRate(CellRessources res);
string getName();
}
}