using System; using System.Text.Json; using System.Text.Json.Serialization; namespace BaseCellSimulation { /// /// Container, der die aktuellen Ressourcen einer Zelle hält und Hilfsfunktionen bietet. /// public class CellRessources { public Resources Res; public EnviromentState Env = new(); [JsonPropertyName("energy")] public EnergyPool energyPool; public Dictionary Resources => new Dictionary(); 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(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 --- /// /// Erzeugt eine CellRessources-Instanz mit vernünftigen Startwerten (grobe physiologische Annahmen). /// Alle Werte in mM, falls nicht anders kommentiert. /// 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) // ------------------------------------------------------------ /// Energiemengen: ATP/ADP/AMP + NAD/NADH + GTP/GDP public struct EnergyPool { /// /// Adenosine-triphosphate /// public double ATP; /// /// Adenosine diphosphate /// public double ADP; /// /// Adenosine monophosphat /// public double AMP; /// /// Nicotinamide adenine dinucleotide /// public double NAD; /// /// Nicotinamide adenine dinucleotide /// public double NADH; /// /// Nicotinamide adenine dinucleotide phosphate /// public double NADPH; /// /// Guanosintriphosphat /// public double GTP; /// /// Guanosindiphosphat /// public double GDP; /// /// inorganic phosphate /// public double Pi; /// /// Pyrophosphat /// public double PPi; } /// Inorganische Phosphate public struct Phosphate { /// /// inorganic phosphate /// public double Pi; /// /// Pyrophosphat /// public double PPi; } /// Kohlenstoff- / Glykolyse-Intermediaten public struct CarbonPool { public double Glucose; /// /// Glucose-6-phosphate /// public double G6P; /// /// Fructose-6-phosphate /// public double F6P; /// /// Fructose 1,6-bisphosphate /// public double F1_6BP; /// /// Glycerinaldehyd-3-phosphat /// public double GA3P; /// /// 1,3-Bisphosphoglycerat /// public double PBG13; /// /// 3-Phosphoglycerat /// public double PG3; /// /// 2-Phosphoglycerat /// public double PG2; /// /// Phosphoenolpyruvat /// public double PEP; public double Pyruvate; public double Lactate; public double CO2; public double AcetylCoA; } /// Proteine, Nukleotide, mRNA, etc. public struct ProteinPool { public double AminoAcids; public double FunctionalProteins; public double Waste; public double NucleicAcids; public double Nucleotides; /// /// Nukleosidtriphosphate /// public double NTP; /// /// Desoxyribonukleotidtriphosphate /// public double dNTP; public double mRNA; public double DNA_damage; public double AcetylCoA; /// /// S-Adenosylmethionin /// public double SAM; /// /// Methionine /// public double MET; /// /// S-Adenosylhomocystein /// public double SAH; public double Homocystein; public double Adenosin; internal double tRNA; internal double Aminoacyl_tRNA; } /// Ionen und kleine Signalmoleküle public struct IonPool { public double Protons; // H+ (vereinfachte Einheit mM) /// /// reactive oxygen species /// public double ROS; /// /// NAtrium-Ionen /// public double Na; /// /// Kalium-Ionen /// public double K; public double H2O2; } public struct Cofactor { public double B12; } public struct Folates { /// /// Tetrahydrofolsäure /// public double THF { get; internal set; } public double MethylTHF { get; internal set; } } public struct NucleusRessources { public double ChromatinAccessibility; public double ReplicationProgress; } /// Gesammelte Ressourcen einer Zelle 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; } /// /// Ein einfaches Modell des zellulären Calcium-Haushalts. /// Werte in mM; Defaultwerte sind phänotypisch realistisch gewählt. /// 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(); } }