InitalCommit

This commit is contained in:
WyanMueller
2025-11-16 10:30:26 +01:00
parent 8b0b73bba8
commit d2e409d10f
73 changed files with 3209 additions and 0 deletions
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
+115
View File
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation
{
public struct cellInfo
{
public double time;
public CellState state;
public Dictionary<string, double> resources;
public CellCaState caState;
public override string ToString()
{
StringBuilder sb = new();
sb.AppendLine($"Time: {time}, State: {state}");
foreach (var kvp in resources)
{
sb.AppendLine($"{kvp.Key}: {kvp.Value}");
}
return sb.ToString();
}
}
public class Cell
{
private List<Organell> organelles = new();
private CellRessources resources;
private CellState state = CellState.Resting;
private double time = 0.0;
private Random rng = new();
private CellCaState caState = new();
public EnviromentState EnviromentState { get { return resources.Env; } set { resources.Env = value; } }
public Cell()
{
organelles.Add(new Cytosol());
organelles.Add(new Mitochondrion());
organelles.Add(new Nucleus());
organelles.Add(new Membrane());
organelles.Add(new Lysosome());
resources = CellRessources.InitDefaults();
// calcium baseline
caState.CytosolicCa = 0.0001; // 100 nM
caState.ER_Ca = 0.5; // 0.5 mM
}
public void Step(double dt)
{
foreach (Organell organell in organelles)
{
organell.calculateRate(resources);
}
foreach (Organell organell in organelles)
{
organell.applyChanges(resources, dt);
}
CheckForDeath(dt);
time += dt;
}
private void CheckForDeath(double dt)
{
// Energie- und Calciumkritische Schwellen
const double ATP_MIN = 0.05; // mM
const double CA_TOXIC = 0.002; // 2 µM
const double WASTE_MAX = 5.0; // mM
if (resources.Res.Energy.ATP < ATP_MIN || caState.CytosolicCa > CA_TOXIC || resources.Res.Protein.Waste > WASTE_MAX)
{
// langsamer Zelltod
if (rng.NextDouble() < 0.1 * dt)
state = CellState.Apoptosis;
}
if (state == CellState.Apoptosis)
{
// Zelle verliert Ressourcen über Zeit
resources.Res.Energy.ATP *= (1.0 - 0.05 * dt);
resources.Res.Carbon.Glucose *= (1.0 - 0.03 * dt);
resources.Res.Protein.AminoAcids *= (1.0 - 0.02 * dt);
}
}
public cellInfo GetCellInfo()
{
return new cellInfo
{
time = this.time,
state = this.state,
resources = new Dictionary<string, double>
{
{ "Glucose", resources.Res.Carbon.Glucose },
{ "Oxygen", resources.Res.Oxygen },
{ "ATP", resources.Res.Energy.ATP },
{ "NAD", resources.Res.Energy.NAD },
{ "NADH", resources.Res.Energy.NADH },
{ "AminoAcids", resources.Res.Protein.AminoAcids }
},
caState = this.caState
};
}
}
}
+101
View File
@@ -0,0 +1,101 @@
using BaseCellSimulation.Enzyms;
using BaseCellSimulation.Enzyms.Cytosol;
using BaseCellSimulation.Enzyms.Cytosol.Ribosomen;
namespace BaseCellSimulation
{
/// <summary>
/// Cellliquid builds ATP and NADH out of Glucosis
/// </summary>
/// <param name="cellname"></param>
/// <param name="vmax"></param>
/// <param name="km"></param>
public class Cytosol : Organell
{
public readonly List<InternalEnzym> enzyms = new List<InternalEnzym>();
double ROS_base_rate = 1e-6;
private readonly string name;
private double rosProduction;
private double vOx;
public Cytosol() : this("Cytosol") { }
public Cytosol(string cellname)
{
name = cellname;
enzyms.Add(new Aldolase());
enzyms.Add(new AdenylateKinase());
enzyms.Add(new Enolase());
enzyms.Add(new GAPDH());
enzyms.Add(new Hexokinasis());
enzyms.Add(new Lactat_Dehydrogenase());
enzyms.Add(new PhosphoFructokinase());
enzyms.Add(new Phosphoglucose_Isomerase());
enzyms.Add(new Phosphoglycerat_Kinase());
enzyms.Add(new Phosphoglycerat_Mutase());
enzyms.Add(new Pyruvat_Kinase());
enzyms.Add(new Pyrophosphatase());
enzyms.Add(new Methionin_Adenosyltransferase());
enzyms.Add(new AHCY());
enzyms.Add(new Methioninsynthase());
enzyms.Add(new Ribosome());
enzyms.Add(new AminoacylTRNASynthetase());
enzyms.Add(new PeptidylTransferase());
enzyms.Add(new NucleosideDiphosphateKinase());
}
//Todo split in compute Rate and apply changes
// Stoichiometrie: 1 Glu -> 2 ATP + 2 NADH (simplyfied)
public void applyChanges(CellRessources Resources, double dt)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ApplyChanges(Resources, dt);
}
// Wenn O2 vorhanden: Pyruvat->CO2 + NADH via PDH/ TCA(vereinfacht)
// Simpler oxidativer Pfad (nur wenn genug O2)
double oxUsage = Math.Min(Resources.Res.Carbon.Pyruvate, vOx * dt); // skaliert mit O2
Resources.Res.Carbon.Pyruvate -= oxUsage;
Resources.Res.Carbon.CO2 += oxUsage; // CO2 als Waste
Resources.Res.Oxygen -= 6.0 * oxUsage; // oxidativer Stoffwechsel erzeugt NADH (vereinfachung) und ATP (nicht durch Glykolyse)
Resources.TransferNADH(3.0 * oxUsage, false); // Beispielzahl
Resources.RegenerateATP(12.0 * oxUsage); // sehr grobe Näherung für oxidative Phosphorylierung
//ROS - Produktion: steigt mit hohem NADH/ NAD Verhältnis und mittlerem / hohem O2
Resources.Res.Ions.ROS += rosProduction * dt;
}
public string getName()
{
return name;
}
public void calculateRate(CellRessources res)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ComputeRate(res.Res);
}
double oxscaled = res.Res.Oxygen * 1000;
vOx = (oxscaled > 1e-3 && res.Res.Carbon.Pyruvate > 0) ? 0.5 * (oxscaled / (oxscaled + 5.0)) : 0.0;
if (oxscaled > 1e-3 && res.Res.Carbon.Pyruvate > 0)
{
}
double redoxRatio = (res.Res.Energy.NADH + 1e-12) / Math.Max(1e-12, res.Res.Energy.NAD);
rosProduction = ROS_base_rate * redoxRatio * (oxscaled / (oxscaled + 5.0));
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class AHCY : InternalEnzym
{
public AHCY()
{
Km = 0.02;
Vmax = 0.3;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dSAH = Math.Min(rate * dt, res.Res.Protein.SAH);
res.Res.Protein.SAH -= dSAH;
res.Res.Protein.Homocystein += dSAH;
res.Res.Protein.Adenosin += dSAH;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.SAH);
}
}
}
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class AdenylateKinase : InternalEnzym
{
public AdenylateKinase()
{
Km = 0.1;
Vmax = 5;
Keq = 1.1;
KmRange = new(0.01, 0.5);
VmaxRange = new(0.5, 15);
KeqRange = new(0.9, 1.2);
}
public double Keq { get; set; }
public ValueRange KeqRange;
public override void ApplyChanges(CellRessources res, double dt)
{
double d = rate * dt;
// Begrenzen, damit keine negativen Konzentrationen entstehen
if (d > 0.0)
{
// Vorwärtsrichtung: 2 ADP -> ATP + AMP
double limit = Math.Min(res.Res.Energy.ADP / 2.0, d);
res.Res.Energy.ADP -= 2.0 * limit;
res.Res.Energy.ATP += limit;
res.Res.Energy.AMP += limit;
}
else if (d < 0.0)
{
// Rückwärtsrichtung: ATP + AMP -> 2 ADP
double limit = Math.Min(Math.Min(res.Res.Energy.ATP, res.Res.Energy.AMP), -d);
res.Res.Energy.ADP += 2.0 * limit;
res.Res.Energy.ATP -= limit;
res.Res.Energy.AMP -= limit;
}
}
public override void ComputeRate(Resources res)
{
double numerator = res.Energy.ADP * res.Energy.ADP - res.Energy.ATP * res.Energy.AMP / Keq;
double denominator = Km * Km + res.Energy.ADP * res.Energy.ADP;
rate = Vmax * (numerator / denominator); // Nettoreaktionsrate in mM/s
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Aldolase : InternalEnzym
{
public Aldolase()
{
Km = 0.1;
Vmax = 10;
KmRange = new(0.01, 0.3);
VmaxRange = new(2, 20);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.FBP);
res.Res.Carbon.FBP -= used;
res.Res.Carbon.GAP += 2 * used;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.FBP);
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Enolase : InternalEnzym
{
public Enolase()
{
Km = 0.1;
Vmax = 10;
KmRange = new(0.01, 0.3);
VmaxRange = new(2, 25);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.PG2);
res.Res.Carbon.PG2 -= used;
res.Res.Carbon.PEP += used;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.PG2);
}
}
}
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class GAPDH : InternalEnzym
{
public GAPDH()
{
Km = 0.1;
Km_NAD = 0.075;
Vmax = 10;
KmRange = new(0.01, 0.5);
VmaxRange = new(2, 25);
Km_NAD_Range = new(0.01, 0.2);
}
public double Km_NAD { get; set; }
public ValueRange Km_NAD_Range { get; private set; }
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, Math.Min(res.Res.Carbon.GAP, res.Res.Energy.NAD));
res.Res.Carbon.GAP -= used;
res.Res.Carbon.PBG13 += used;
res.TransferNADH(used, false);
res.Res.Ions.Protons += 1.0 * used;
}
public override void ComputeRate(Resources res)
{
rate = Vmax * (res.Carbon.GAP / (Km + res.Carbon.GAP)) * (res.Energy.NAD / (Km_NAD + res.Energy.NAD));
}
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Hexokinasis : InternalEnzym
{
public Hexokinasis() {
Km = 0.05;
Vmax = 5;
KmRange = new(0.01, 0.1);
VmaxRange = new(0.5, 20);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, Math.Min(res.Res.Carbon.Glucose, res.Res.Energy.ATP));
res.Res.Carbon.Glucose -= used;
res.Res.Carbon.G6P += used;
res.ConsumeATP(used);
res.Res.Ions.Protons += used;
}
//todo noch machen dass atpberücksichtigt wird
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.Glucose);
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Lactat_Dehydrogenase : InternalEnzym
{
public Lactat_Dehydrogenase()
{
Km = 0.5;
Vmax = 10;
KmRange = new(0.05,2);
VmaxRange = new(2, 25);
Km_NADH = 0.05;
Km_NADH_Range = new(0.005, 0.2);
}
public double Km_NADH { get; set; }
public ValueRange Km_NADH_Range { get; set; }
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, Math.Min(res.Res.Carbon.Pyruvate, res.Res.Energy.NADH));
//LDH Lactat production and NAD+ regeneration
res.Res.Carbon.Pyruvate -= used;
res.Res.Carbon.Lactate += used;
res.TransferNADH(used,true);
//Consume Protons
res.Res.Ions.Protons -= 1.0 * used;
}
public override void ComputeRate(Resources res)
{
double oxscaled = res.Oxygen * 1000;
double o2Factor = Math.Max(0.0, 1.0 - oxscaled / (oxscaled + 10.0));
rate = Vmax * o2Factor
* (res.Carbon.Pyruvate / (Km + res.Carbon.Pyruvate))
* (res.Energy.NADH / (Km_NADH + res.Energy.NADH));
}
}
}
@@ -0,0 +1,38 @@
using BaseCellSimulation.Enzyms.Membrane;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Methionin_Adenosyltransferase : InternalEnzym
{
public double Km_ATP { get; set; }
public Methionin_Adenosyltransferase()
{
Km = 0.05;
Vmax = 0.5;
Km_ATP = 0.2;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dSAM = Math.Min(rate * dt,res.Res.Energy.ATP);
res.Res.Protein.MET -= dSAM;
res.Res.Protein.SAM += dSAM;
res.Res.Energy.ATP -= dSAM;
res.Res.Phosphate.PPi += dSAM;
res.Res.Phosphate.Pi += dSAM;
}
public override void ComputeRate(Resources res)
{
rate = Vmax * (res.Protein.MET / (Km + res.Protein.MET)) * (res.Energy.ATP / (Km_ATP + res.Energy.ATP));
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Methioninsynthase : InternalEnzym
{
public Methioninsynthase()
{
Km = 0.015;
Vmax = 0.2;
}
public override void ApplyChanges(CellRessources res, double dt)
{
// Berechne tatsächlich mögliche Umwandlung
double dHcy = Math.Min(rate * dt, res.Res.Protein.Homocystein);
dHcy = Math.Min(dHcy, res.Res.Folate.MethylTHF);
dHcy = Math.Min(dHcy, res.Res.Cofactor.B12); // Co-Faktor limitierend
if (dHcy <= 0)
return;
// Verbrauch von Substraten
res.Res.Protein.Homocystein -= dHcy;
res.Res.Folate.MethylTHF -= dHcy;
// Cofaktor-B12 wird nicht dauerhaft verbraucht (Katalytisch)
// kann aber langsam inaktiviert werden, falls du das modellieren willst
// Bildung von Produkten
res.Res.Protein.MET += dHcy;
res.Res.Folate.THF += dHcy;
}
public override void ComputeRate(Resources res)
{
// Aktivitätsfaktor abhängig vom verfügbaren B12
double cofactorEffect = Math.Clamp(res.Cofactor.B12 / 0.01, 0.0, 1.0);
// Michaelis-Menten über Homocystein
Michaelis_Menten(res.Protein.Homocystein);
rate *= cofactorEffect;
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class NucleosideDiphosphateKinase : InternalEnzym
{
private const double k_eq = 0.25; // 0.25 / s → recht schnell, da NDK sehr aktiv ist
public NucleosideDiphosphateKinase()
{
Km = 0.05; // unspezifisch, da das Enzym viele Nukleotide akzeptiert
Vmax = 1.0; // fiktiver Maximalumsatz (mmol/L·s)
}
public override void ApplyChanges(CellRessources res, double dt)
{
var energy = res.Res.Energy;
// --- Austausch zwischen ATP und GTP ---
double delta = (energy.ATP - energy.GTP) * k_eq * dt;
if (Math.Abs(delta) < 1e-9)
return;
// Begrenzung: kein negativer Pool
if (delta > 0)
{
delta = Math.Min(delta, energy.ATP);
}
else
{
delta = Math.Max(delta, -energy.GTP);
}
// Umsetzung: ATP -> GTP oder umgekehrt
energy.ATP -= delta;
energy.GTP += delta;
}
public override void ComputeRate(Resources res)
{
double diff = Math.Abs(res.Energy.ATP - res.Energy.GTP);
Michaelis_Menten(diff);
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class PhosphoFructokinase : InternalEnzym
{
public PhosphoFructokinase()
{
Km = 0.2;
Vmax = 7;
KmRange = new(0.05, 0.5);
VmaxRange = new(1, 25);
}
public double Ki_ATP_PFK { get; set; }
public double Ka_AMP_PFK { get; set; }
public double h_AMP { get; set; }
public double h_ATP { get; set; }
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, Math.Min(res.Res.Energy.ATP, res.Res.Carbon.F6P));
res.Res.Carbon.F6P -= used;
res.Res.Carbon.FBP += used;
res.ConsumeATP(used);
res.Res.Ions.Protons += used;
}
public override void ComputeRate(Resources res)
{
double inhibition = 1.0 / (1.0 + Math.Pow(res.Energy.ATP / Ki_ATP_PFK, h_ATP)); // Hemmung durch ATP
double activation = 1.0 + Math.Pow(res.Energy.AMP / Ka_AMP_PFK, h_AMP); // Aktivierung durch AMP
rate = Michaelis_Menten(res.Carbon.F6P, Vmax * inhibition * activation, Km);
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Phosphoglucose_Isomerase : InternalEnzym
{
public Phosphoglucose_Isomerase()
{
Km = 0.1;
Vmax = 10;
KmRange = new(0.05, 0.2);
VmaxRange = new(0.5, 30);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.G6P);
res.Res.Carbon.G6P -= used;
res.Res.Carbon.F6P += used;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.G6P);
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Phosphoglycerat_Kinase : InternalEnzym
{
public Phosphoglycerat_Kinase()
{
Vmax = 10;
Km = 0.1;
KmRange = new(0.01, 0.3);
VmaxRange = new(2, 30);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.PBG13);
res.Res.Carbon.PBG13 -= used;
res.Res.Carbon.PG3 += used;
res.RegenerateATP(used);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.PBG13);
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Phosphoglycerat_Mutase : InternalEnzym
{
public Phosphoglycerat_Mutase()
{
Km = 0.1;
Vmax = 10;
VmaxRange = new(2, 30);
KmRange = new(0.01, 0.3);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.PG3);
res.Res.Carbon.PG3 -= used;
res.Res.Carbon.PG2 += used;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.PG3);
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Pyrophosphatase : InternalEnzym
{
public Pyrophosphatase()
{
Vmax = 2.0;
Km = 0.01;
VmaxRange = new(1, 10);
KmRange = new(0.001, 0.05);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dPPi = Math.Max(rate, res.Res.Phosphate.PPi);
res.HydrolyzePPi(dPPi);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Phosphate.PPi);
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol
{
public class Pyruvat_Kinase : InternalEnzym
{
public Pyruvat_Kinase()
{
Km = 0.1;
Vmax = 10;
KmRange = new(0.01, 0.3);
VmaxRange = new(2, 25);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Carbon.PEP);
res.Res.Carbon.PEP -= used;
res.Res.Carbon.Pyruvate += used;
res.RegenerateATP(used);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.PEP);
}
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol.Ribosomen
{
public class AminoacylTRNASynthetase : InternalEnzym
{
public AminoacylTRNASynthetase()
{
Km = 0.1;
Vmax = 1.5;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dAAtRNA = Math.Min(rate * dt, Math.Min(res.Res.Protein.AminoAcids, res.Res.Protein.tRNA));
dAAtRNA = Math.Min(dAAtRNA, res.Res.Energy.ATP);
res.Res.Protein.AminoAcids -= dAAtRNA;
res.Res.Protein.tRNA -= dAAtRNA;
res.Res.Protein.Aminoacyl_tRNA += dAAtRNA;
res.ConsumeATP(dAAtRNA);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.tRNA);
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol.Ribosomen
{
public class PeptidylTransferase : InternalEnzym
{
public PeptidylTransferase()
{
Km = 0.05;
Vmax = 5.0;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dPeptide = Math.Min(rate * dt, Math.Min(res.Res.Protein.Aminoacyl_tRNA, res.Res.Energy.GTP));
res.Res.Protein.Aminoacyl_tRNA -= dPeptide;
res.Res.Protein.FunctionalProteins += dPeptide;
res.Res.Energy.GTP -= dPeptide;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.Aminoacyl_tRNA);
}
}
}
@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol.Ribosomen
{
public class Ribosome : InternalEnzym
{
private TranslationFactor initiation;
private TranslationFactor elongation;
private TranslationFactor termination;
private const double ProteinPermRNA = 20.0;
int ribosomenState = 0;
public Ribosome()
{
Km = 0.5; // fiktiv (abhängig von mRNA)
Vmax = 10.0; // z. B. 10 Aminosäuren pro Sekunde
initiation = new TranslationFactor(TranslationFactor.FactorType.Initiation);
elongation = new TranslationFactor(TranslationFactor.FactorType.Elongation);
termination = new TranslationFactor(TranslationFactor.FactorType.Termination);
}
private double availableAA = 0;
private double dProtein = 0;
public override void ApplyChanges(CellRessources res, double dt)
{
int safety = 0;
while (safety++ < 10)
{
switch (ribosomenState)
{
case 0:
availableAA = res.Res.Protein.AminoAcids;
dProtein = rate * dt;
// Translation start -> Initiationsfaktoren verbrauchen GTP
initiation.ApplyChanges(res, dt * 0.5);
if (initiation.TranslationSpeed > 0)
{
dProtein = Math.Min(initiation.TranslationSpeed, dProtein);
dProtein = Math.Min(dProtein, Math.Min(res.Res.Protein.mRNA, availableAA));
res.Res.Protein.AminoAcids -= dProtein;
res.Res.Protein.FunctionalProteins += dProtein;
ribosomenState = 1;
}
else return;
break;
case 1:
elongation.ApplyChanges(res, dt * dProtein * 0.1);
if (elongation.TranslationSpeed > 0)
{
dProtein = Math.Min(elongation.TranslationSpeed, dProtein);
// mRNA-Abnutzung: jede mRNA kann nur begrenzt oft benutzt werden
double used_mRNA = dProtein / ProteinPermRNA;
res.Res.Protein.mRNA -= used_mRNA;
// Abbauprodukte: ein Teil recycelt, ein Teil wird zu Waste
double degraded = used_mRNA * 0.8;
double lost = used_mRNA * 0.2;
res.Res.Protein.Nucleotides += degraded; // Rückgewinn von Basen
res.Res.Protein.Waste += lost; // Restliche RNA-Fragmente als Zellabfall
ribosomenState = 2;
}
else return;
break;
case 2:
termination.ApplyChanges(res, dt * 0.01 * dProtein);
if (termination.TranslationSpeed > 0)
{
res.ConsumeATP(dProtein * 4); // z. B. 4 ATP pro Peptidbindung -> ADP
ribosomenState = 0;
}
else return;
break;
}
}
}
public override void ComputeRate(Resources res)
{
if (ribosomenState == 0) {
if (res.Protein.AminoAcids <= 0.0 || res.Protein.mRNA <= 0.0)
return;
double availablemRNA = res.Protein.mRNA;
Michaelis_Menten(availablemRNA);
initiation.ComputeRate(res);
elongation.ComputeRate(res);
termination.ComputeRate(res);
}
}
}
}
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Cytosol.Ribosomen
{
/*
* Faktor Aufgabe Energieverbrauch
* IF (Initiation Factors) Ribosom startet Translation 1 GTP
* EF-Tu, EF-G (Elongation) tRNA Positionierung, Translokation 12 GTP pro Zyklus
* RF (Release Factors) Beendet Translation an Stoppcodon 1 GTP
*/
internal class TranslationFactor : InternalEnzym
{
public enum FactorType { Initiation, Elongation, Termination }
public FactorType Type { get; }
public double TranslationSpeed;
public TranslationFactor(FactorType type)
{
Type = type;
Km = 0.1;
Vmax = 2.0;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Energy.GTP);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(rate * dt, res.Res.Energy.GTP);
res.Res.Energy.GTP -= used;
res.Res.Energy.GDP += used;
TranslationSpeed = used;
}
}
}
+50
View File
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms
{
public abstract class Enzym
{
/// <summary>
/// mM/S
/// </summary>
public double Vmax { get; set; }
/// <summary>
/// mM
/// </summary>
public double Km { get; set; }
public ValueRange VmaxRange { get; protected set; }
public ValueRange KmRange { get; protected set; }
protected double rate;
protected void Michaelis_Menten(double ressource)
{
rate = Michaelis_Menten(ressource, Vmax, Km);
}
protected double Michaelis_Menten(double consumable,double vmax, double km)
{
return (vmax * consumable) / (km + consumable);
}
public abstract void ApplyChanges(CellRessources res, double dt);
}
public abstract class InternalEnzym : Enzym
{
public abstract void ComputeRate(Resources res);
}
public abstract class MembranEnzyme : Enzym
{
public abstract double CalculateGradient(CellRessources res);
public abstract void ComputeRate(double gradient, EnviromentState Env);
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Lysosome
{
public class Cathepsin : InternalEnzym
{
public Cathepsin()
{
Vmax = 0.2; // mM/s, empirisch
Km = 0.1; // mM
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.Waste);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double degraded = rate * dt;
degraded = Math.Min(degraded, res.Res.Protein.Waste);
res.Res.Protein.Waste -= degraded;
res.Res.Protein.AminoAcids += degraded * 0.5; // 50% verwertbar
res.Res.Energy.ATP += degraded * 0.05; // kleine ATP-Rückgewinnung
res.Res.Energy.NADH += degraded * 0.01; // minimale Redoxreaktion
}
}
}
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Lysosome
{
public class GenericLysosomalEnzyme : InternalEnzym
{
public GenericLysosomalEnzyme()
{
Vmax = 0.2;
Km = 0.1;
}
double redoxRatio = 0.0;
public override void ComputeRate(Resources res)
{
// --- Grundrate basierend auf Protein-Waste ---
rate = Michaelis_Menten(res.Protein.Waste, Vmax, Km);
// --- Energieabhängigkeit ---
double energyCharge = (res.Energy.ATP + 0.5 * res.Energy.ADP) /
(res.Energy.ATP + res.Energy.ADP + res.Energy.AMP + 1e-9);
rate *= Math.Clamp(energyCharge, 0.0, 1.0);
// --- Redoxabhängigkeit ---
redoxRatio = res.Energy.NAD / (res.Energy.NAD + res.Energy.NADH + 1e-9);
rate *= Math.Clamp(redoxRatio, 0.0, 1.0);
// --- pH-Abhängigkeit ---
double acidFactor = 1.0 - 0.5 * Math.Clamp(res.Ions.Protons / 1.0, 0.0, 1.0);
rate *= acidFactor;
// --- Stressfaktor bei hohen ROS ---
double stressPenalty = res.Ions.ROS > 1.0 ? 0.5 : 1.0;
rate *= stressPenalty;
}
public override void ApplyChanges(CellRessources Resources, double dt)
{
var res = Resources.Res;
var ca = Resources.Res.Ca;
ComputeRate(res);
double degraded = Math.Min(res.Protein.Waste, rate * dt);
if (degraded <= 0.0)
return;
// --- Protein-Abbau ---
res.Protein.Waste -= degraded;
// --- Energieverbrauch & minimale Rückgewinnung ---
double atpUsed = degraded * 0.15;
double atpRecovered = degraded * 0.03 * ((res.Energy.ATP + 0.5 * res.Energy.ADP) /
(res.Energy.ATP + res.Energy.ADP + res.Energy.AMP + 1e-9));
Resources.ConsumeATP(atpUsed);
res.Energy.ATP += atpRecovered;
// --- NAD+ → NADH Redoxreaktion ---
double nadUsed = degraded * 0.08;
double actualNadUsed = Math.Min(nadUsed, res.Energy.NAD);
res.Energy.NAD -= actualNadUsed;
res.Energy.NADH += actualNadUsed;
// --- Aminosäuren-Recycling ---
double recyclingEfficiency = 0.4 + 0.3 * ((res.Energy.ATP + 0.5 * res.Energy.ADP) /
(res.Energy.ATP + res.Energy.ADP + res.Energy.AMP + 1e-9));
res.Protein.AminoAcids += degraded * recyclingEfficiency;
// --- Sekundäre Effekte: ROS, Heat, Protonen ---
res.Ions.ROS += degraded * (1.0 - redoxRatio) * 0.01;
res.Heat += degraded * 0.05;
res.Ions.Protons += degraded * 0.005;
// --- Kalziumleckage als Stresssignal ---
ca.CytosolicCa += degraded * 0.00002;
// --- Lysosomenaktivität für Feedback ---
ca.LysosomeActivity = Math.Clamp(rate / Vmax, 0.0, 1.0);
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Lysosome
{
public class LysosomalLipase : InternalEnzym
{
public LysosomalLipase()
{
Vmax = 0.1;
Km = 0.05;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Lipids); // falls Lipide modelliert werden
}
public override void ApplyChanges(CellRessources res, double dt)
{
double degraded = rate * dt;
degraded = Math.Min(degraded, res.Res.Lipids);
res.Res.Lipids -= degraded;
res.Res.Energy.ATP += degraded * 0.02; // minimaler ATP Gewinn
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Lysosome
{
public class LysosomalNuclease : InternalEnzym
{
public LysosomalNuclease()
{
Vmax = 0.15;
Km = 0.05;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.NucleicAcids); // falls RNA/DNA modelliert
}
public override void ApplyChanges(CellRessources res, double dt)
{
double degraded = rate * dt;
degraded = Math.Min(degraded, res.Res.Protein.NucleicAcids);
res.Res.Protein.NucleicAcids -= degraded;
res.Res.Protein.Nucleotides += degraded; // freiwerdende Nucleotide
res.Res.Energy.ATP += degraded * 0.01;
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Lysosome
{
public class LysosomalPhosphatase : InternalEnzym
{
public LysosomalPhosphatase()
{
Vmax = 0.1;
Km = 0.05;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.PhosphorylatedSubstrates);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double degraded = rate * dt;
degraded = Math.Min(degraded, res.Res.PhosphorylatedSubstrates);
res.Res.PhosphorylatedSubstrates -= degraded;
res.Res.Phosphate.Pi += degraded;
res.Res.Phosphate.PPi += degraded * 0.1; // falls Pyrophosphat entsteht
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane.GLUT
{
public class GLUT1 : MembranEnzyme
{
public GLUT1()
{
Km = 1.5; // Example Km value in mM
Vmax = 0.5;
KmRange = new(1.0, 3.0);
VmaxRange = new(0.1, 10.0);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = Math.Min(res.Env.Glucose, rate * dt);
res.Env.Glucose -= flux;
res.Res.Carbon.Glucose += flux;
}
public override double CalculateGradient(CellRessources res)
{
return res.Env.Glucose - res.Res.Carbon.Glucose;
}
public override void ComputeRate(double gradient, EnviromentState Env)
{
if (gradient <= 0)
{
rate = 0;
return;
}
Michaelis_Menten(gradient);
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane.GLUT
{
public class GLUT2 : GLUT1
{
public GLUT2()
{
Km = 17.0; // Example Km value in mM
Vmax = 1.2;
KmRange = new(15.0, 20.0);
VmaxRange = new(1.0, 50.0);
}
}
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane.GLUT
{
public class GLUT3 : GLUT1
{
public GLUT3()
{
Km = 1.0;
Vmax = 0.8;
KmRange = new(0.3, 1.0);
VmaxRange = new(0.5, 20.0);
}
}
}
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane.GLUT
{
public class GLUT4 : GLUT1
{
public GLUT4()
{
Km = 5.0; // Example Km value in mM for GLUT4
Vmax = 0.6; // Higher Vmax for GLUT4
ActivationThreshold = 0.3; // Example threshold for insulin activation
KmRange = new(4.0, 6.0);
VmaxRange = new(0.2, 15.0);
}
public double ActivationThreshold { get; set; }
public override void ComputeRate(double gradient, EnviromentState Env)
{
if (gradient <= 0)
{
rate = 0;
return;
}
// GLUT4 is insulin-responsive, so we can add an insulin factor
double insulinFactor = 0.5 * (Math.Tanh((Env.Insulin - ActivationThreshold) / 0.1) + 1.0); // Example: insulin increases rate up to 3x
Michaelis_Menten(gradient);
rate *= insulinFactor;
}
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane
{
public class KLeakChannel : MembranEnzyme
{
public double Permeability = 0.01; // 1/s, diffusionsbasiert
public override void ComputeRate(double gradient, EnviromentState env)
{
rate = Permeability * gradient;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = rate * dt;
res.Res.Ions.K -= flux; // aus der Zelle raus
res.Env.K += flux;
}
public override double CalculateGradient(CellRessources res)
{
return res.Res.Ions.K - res.Env.K;
}
}
}
+39
View File
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane
{
public class MCT : MembranEnzyme
{
public override double CalculateGradient(CellRessources res)
{
double hGradient = Math.Pow(10, -res.pH_in) / Math.Pow(10, -res.pH_ext);
return res.Res.Carbon.Lactate - res.Env.Lactate * hGradient;
}
public override void ComputeRate(double Gradient, EnviromentState env)
{
if (Gradient <= 0)
{
rate = 0;
return;
}
Michaelis_Menten(Gradient);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = rate * dt;
res.Res.Carbon.Lactate -= flux; // Laktat raus
res.Env.Lactate += flux;
res.Res.Ions.Protons -= flux; // Protonen raus (Symport)
res.Env.Protons += flux;
}
}
}
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane
{
/// <summary>
/// Na+/Ca2+ Exchanger (3 Na⁺ in / 1 Ca²⁺ out)
/// Einfaches Michaelis-Menten-basiertes Modell mit Gradienten
/// </summary>
public class NCX : MembranEnzyme
{
public double NaStoich = 3.0; // Na⁺ pro Ca²⁺
public double CaStoich = 1.0;
/// <summary>
/// Berechnet die Transport-Rate abhängig von zellinternen und externen Ionenkonzentrationen
/// </summary>
public override void ComputeRate(double gradient, EnviromentState env)
{
// Michaelis-Menten-ähnliche Sättigung
rate = Vmax * gradient / (Km + Math.Abs(gradient));
}
/// <summary>
/// Wendet den Transport auf die Zellressourcen an
/// </summary>
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = rate * dt;
// Na+ in die Zelle
res.Res.Ions.Na += NaStoich * flux;
res.Env.Na -= NaStoich * flux;
// Ca2+ aus der Zelle
res.Res.Ca.CytosolicCa -= CaStoich * flux;
res.Env.Ca += CaStoich * flux;
}
public override double CalculateGradient(CellRessources res)
{
// Gradienten: innen - außen
double naGradient = res.Res.Ions.Na - res.Env.Na; // mM
double caGradient = res.Res.Ca.CytosolicCa - res.Env.Ca; // mM
// Richtung: positiv = Ca raus / Na rein
return (naGradient / NaStoich) - (caGradient / CaStoich);
}
}
}
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane
{
public class NaK_ATPase : MembranEnzyme
{
public double ATPperCycle = 1.0;
public double NaOutStoich = 3.0;
public double KInStoich = 2.0;
public override void ComputeRate(double gradient, EnviromentState env)
{
// niedriger Gradient → höhere Rate
double effective = 1.0 / (1.0 + gradient);
rate = Vmax * effective;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = rate * dt;
// Verbrauch von ATP
double atpNeeded = flux * ATPperCycle;
if (res.Res.Energy.ATP < atpNeeded) flux *= res.Res.Energy.ATP / atpNeeded;
res.Res.Ions.Na -= NaOutStoich * flux; // Na raus
res.Res.Ions.K += KInStoich * flux; // K rein
res.Env.Na += NaOutStoich * flux;
res.Env.K -= KInStoich * flux;
res.ConsumeATP(atpNeeded);
}
public override double CalculateGradient(CellRessources res)
{
return (res.Res.Ions.Na / res.Env.Na) * (res.Env.K / res.Res.Ions.K);
}
}
}
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Membrane
{
// ----------------------------------------------------------
// 3. PMCA Ca²⁺-ATPase (Ca raus, ATP-abhängig)
// ----------------------------------------------------------
public class PMCA : MembranEnzyme
{
public double ATPperCycle = 1.0;
public override void ComputeRate(double caCyt, EnviromentState env)
{
// klassisch: Michaelis-Menten mit Ca²⁺-Abhängigkeit
rate = Michaelis_Menten(caCyt, Vmax, Km);
}
public override void ApplyChanges(CellRessources res, double dt)
{
double flux = rate * dt;
double atpNeeded = flux * ATPperCycle;
if (res.Res.Energy.ATP < atpNeeded) flux *= res.Res.Energy.ATP / atpNeeded;
res.Res.Ca.CytosolicCa -= flux; // Ca raus
res.Env.Ca += flux;
res.ConsumeATP(atpNeeded);
}
public override double CalculateGradient(CellRessources res)
{
return res.Res.Ca.CytosolicCa; // PMCA is not driven by a concentration gradient
}
}
}
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// Noch gemacht werden
namespace BaseCellSimulation.Enzyms.Mytochondrion
{
public class ANTTransporter : InternalEnzym
{
public ANTTransporter()
{
Vmax = 0.3;
Km = 0.02; // mM ADP
}
public override void ApplyChanges(CellRessources res, double dt)
{
double adpAvailable = res.Res.Energy.ADP;
double atpAvailable = res.Res.Energy.ATP;
double transportable = Math.Min(adpAvailable, rate * dt);
transportable = Math.Min(transportable, atpAvailable); // Sicherstellen, dass genug ATP zum Tausch vorhanden ist
if (transportable <= 0) return;
res.Res.Energy.ADP -= transportable;
res.Res.Energy.ATP += transportable;
}
public override void ComputeRate(Resources res)
{
double adp = res.Energy.ADP;
Michaelis_Menten(adp);
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Mytochondrion
{
public class ATPSynthase : InternalEnzym
{
public ATPSynthase()
{
Vmax = 0.4;
Km = 0.05; // ADP
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(res.Res.Energy.ADP, rate * dt);
res.RegenerateATP(used);
}
public override void ComputeRate(Resources res)
{
double gradient = Math.Clamp(res.Energy.NADH / (res.Energy.NAD + 1e-9), 0.0, 5.0);
rate = Vmax * (gradient / (Km + gradient));
}
}
}
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Mytochondrion
{
public class OxPhosEnzyme : InternalEnzym
{
public double PO_Ratio { get; set; } = 2.5;
public OxPhosEnzyme()
{
Vmax = 0.8;
Km = 0.01;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double usedNADH = Math.Min(rate * dt, res.Res.Energy.NADH);
if (usedNADH <= 0) return;
res.TransferNADH(usedNADH, true);
double o2Consumed = 0.5 * usedNADH;
res.Res.Oxygen = Math.Max(0.0, res.Res.Oxygen - o2Consumed);
double atpMade = PO_Ratio * usedNADH;
res.RegenerateATP(atpMade);
// ROS-Produktion
double rosFactor = Math.Min(1.0, res.Res.Oxygen / 2.0);
res.Res.Ions.H2O2 += usedNADH * 0.001 * rosFactor;
res.Res.Protein.Waste += usedNADH * 0.001 * rosFactor;
}
public override void ComputeRate(Resources res)
{
double nadh = res.Energy.NADH;
Michaelis_Menten(nadh);
// Begrenzung durch O2
double o2Limit = Math.Min(1.0, res.Oxygen / 0.05);
rate *= o2Limit;
// ATP/ROS Feedback
double atpFactor = Math.Clamp(res.Energy.ATP / 0.5, 0.0, 1.0);
double wasteFactor = 1.0 / (1.0 + res.Protein.Waste / 10.0);
rate *= atpFactor * wasteFactor;
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Mytochondrion
{
public class PyruvateDehydrogenase : InternalEnzym
{
public PyruvateDehydrogenase()
{
Vmax = 1.0; // mM/s
Km = 0.05; // mM Pyruvat
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.Pyruvate);
// Aktivierung durch Ca²⁺
double ca = res.Ca.CytosolicCa;
double caBoost = 1.0 + 0.8 * (ca / (0.0005 + ca)); // bis ~1.8x Boost
rate *= caBoost;
// Hemmung durch hohes NADH/NAD+ Verhältnis oder ATP
double redox = res.Energy.NAD / (res.Energy.NAD + res.Energy.NADH + 1e-9);
double energy = res.Energy.ATP / (res.Energy.ATP + res.Energy.ADP + 1e-9);
rate *= redox * (1.0 - 0.5 * energy); // Hohe Energie hemmt
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(res.Res.Carbon.Pyruvate, rate * dt);
res.Res.Carbon.Pyruvate -= used;
res.Res.Carbon.AcetylCoA += used;
res.TransferNADH(used, false);
res.Res.Carbon.CO2 += used;
}
}
}
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Mytochondrion
{
public class TCAEnzyme : InternalEnzym
{
public TCAEnzyme()
{
Vmax = 0.1; // mM/s
Km = 0.02; // mM Acetyl-CoA
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Carbon.AcetylCoA);
// Abhängig vom Redoxstatus
double redox = res.Energy.NAD / (res.Energy.NAD + res.Energy.NADH + 1e-9);
rate *= redox;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double used = Math.Min(res.Res.Carbon.AcetylCoA, rate * dt);
res.Res.Carbon.AcetylCoA -= used;
res.TransferNADH(2 * used, false);
//res.FADH2 += used;
res.Res.Energy.GTP += used; // optional
res.Res.Carbon.CO2 += 2 * used;
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class DNA_Polymerase_Delta : InternalEnzym
{
private const double EnergyCostATP = 0.5;
public DNA_Polymerase_Delta()
{
Km = 0.05;
Vmax = 1.2;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dDna = Math.Min(rate * dt, res.Res.Protein.dNTP);
dDna = res.Res.Energy.ATP >= dDna * EnergyCostATP ? dDna : res.Res.Energy.ATP / EnergyCostATP;
res.Res.Protein.dNTP -= dDna;
res.Res.Nucleus.ReplicationProgress += dDna;
res.ConsumeATP(dDna * EnergyCostATP);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.dNTP);
}
}
}
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class DNMT1 : InternalEnzym
{
public DNMT1()
{
Km = 0.01;
Vmax = 0.25;
}
public override void ApplyChanges(CellRessources res, double dt)
{
// Berechne tatsächlich übertragene Methylmenge
double dMethyl = Math.Min(rate * dt, res.Res.Protein.SAM);
// Chromatinzugänglichkeit moduliert Effektivität
double accessibilityFactor = Math.Clamp(res.Res.Nucleus.ChromatinAccessibility / 0.005, 0.1, 1.0);
dMethyl *= accessibilityFactor;
// SAM → SAH Umwandlung
res.Res.Protein.SAM -= dMethyl;
res.Res.Protein.SAH += dMethyl; // 1:1 Bildung
// Methylierung der DNA (vereinfachte Darstellung)
res.Res.Nucleus.ChromatinAccessibility -= dMethyl * 0.005;
if (res.Res.Nucleus.ChromatinAccessibility < 0)
res.Res.Nucleus.ChromatinAccessibility = 0;
}
public override void ComputeRate(Resources res)
{
double activityFactor = Math.Min(1.0, res.Nucleus.ReplicationProgress / 10.0);
Michaelis_Menten(res.Protein.SAM * activityFactor);
rate *= activityFactor;
}
}
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class HistoneAcetyltransferase : InternalEnzym
{
public HistoneAcetyltransferase()
{
Km = 0.01;
Vmax = 0.3;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dA = Math.Min(rate * dt, res.Res.Protein.AcetylCoA);
res.Res.Protein.AcetylCoA -= dA;
res.Res.Nucleus.ChromatinAccessibility = Math.Min(1.0, res.Res.Nucleus.ChromatinAccessibility + dA * 0.1);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.AcetylCoA);
}
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class HistoneDeacetylase : InternalEnzym
{
public HistoneDeacetylase()
{
Km = 0.02;
Vmax = 0.25;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dD = Math.Min(rate * dt, Math.Min(res.Res.Nucleus.ChromatinAccessibility / 0.1, res.Res.Energy.NAD));
res.Res.Energy.NAD -= dD;
res.Res.Energy.NADH += dD * 0.5;
res.Res.Nucleus.ChromatinAccessibility = Math.Max(0.0, res.Res.Nucleus.ChromatinAccessibility - dD * 0.1);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Energy.NAD);
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class PARP1 : InternalEnzym
{
private const double EnergyCostATP = 0.3;
public PARP1()
{
Km = 0.02;
Vmax = 0.4;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dRepair = Math.Min(rate * dt, res.Res.Protein.DNA_damage);
dRepair = res.Res.Energy.NAD >= dRepair * EnergyCostATP ? dRepair : res.Res.Energy.NAD / EnergyCostATP;
res.Res.Energy.NAD -= dRepair * EnergyCostATP;
res.Res.Energy.NADH += dRepair * 0.2;
res.Res.Protein.DNA_damage -= dRepair * 0.8;
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.DNA_damage);
}
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class RNA_Polymerase_II : InternalEnzym
{
private const double EnergyCostATP = 0.3;
public RNA_Polymerase_II()
{
Km = 0.02;
Vmax = 0.8;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double dM = Math.Min(rate * dt, res.Res.Protein.NTP);
dM = res.Res.Energy.ATP >= dM * EnergyCostATP ? dM : res.Res.Energy.ATP / EnergyCostATP;
res.Res.Protein.NTP -= dM;
res.Res.Protein.mRNA += dM;
res.ConsumeATP(dM * EnergyCostATP);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.NTP);
rate *= res.Nucleus.ChromatinAccessibility;
}
}
}
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms.Nucleus
{
public class Topoisomerase_II : InternalEnzym
{
private const double EnergyCostATP = 0.2;
public Topoisomerase_II()
{
Km = 0.03;
Vmax = 0.5;
}
public override void ApplyChanges(CellRessources res, double dt)
{
double repair = Math.Min(rate * dt, res.Res.Protein.DNA_damage);
repair = res.Res.Energy.ATP >= repair * EnergyCostATP ? repair : res.Res.Energy.ATP / EnergyCostATP;
res.Res.Protein.DNA_damage -= repair;
res.ConsumeATP(repair * EnergyCostATP);
}
public override void ComputeRate(Resources res)
{
Michaelis_Menten(res.Protein.DNA_damage);
}
}
}
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation.Enzyms
{
public static class VmaxCalculator
{
private const double Avogadro = 6.02214076e23; // mol⁻¹
/// <summary>
/// Berechnet Vmax (in mM/s) aus Enzymkinetik-Parametern.
/// </summary>
/// <param name="kcat">Turnover-Zahl des Enzyms (s⁻¹ pro Molekül)</param>
/// <param name="enzymeCount">Anzahl der Enzymmoleküle in der Zelle</param>
/// <param name="cellVolume_L">Zellvolumen in Litern (z. B. 1e-12 für typische Eukaryoten)</param>
/// <returns>Vmax in mM/s</returns>
public static double ComputeVmax(double kcat, double enzymeCount, double cellVolume_L)
{
// [E_total] = (enzymeCount / Avogadro) / cellVolume
double enzymeConcentration_M = (enzymeCount / Avogadro) / cellVolume_L; // mol/L
double vmax_M_per_s = kcat * enzymeConcentration_M; // mol/L/s
// Umrechnung auf mM/s
return vmax_M_per_s * 1000.0;
}
/// <summary>
/// Beispielausgabe für häufige Zellgrößen / Transporter.
/// </summary>
public static void Example()
{
// Beispielwerte: GLUT1, GLUT2, GLUT3, GLUT4
double cellVolume = 1e-12; // Liter (≈ typische Säugetierzelle)
double[] enzymeCounts = { 1e5, 1e6, 1e7 }; // niedrige, mittlere, hohe Expression
double[] kcats = { 100, 500, 1000 }; // plausible Turnover-Werte
foreach (var kcat in kcats)
{
foreach (var enz in enzymeCounts)
{
double vmax = ComputeVmax(kcat, enz, cellVolume);
Console.WriteLine($"kcat={kcat,5:F0} Enzyme={enz:E0} → Vmax={vmax:F2} mM/s");
}
}
}
}
}
+61
View File
@@ -0,0 +1,61 @@
using BaseCellSimulation.Enzyms;
using BaseCellSimulation.Enzyms.Lysosome;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation
{
/// <summary>
/// Recicling center of the cell takes up waste and generates Amino acides and small amout of ATP
/// </summary>
/// <param name="cellname"></param>
/// <param name="decayRate"></param>
public class Lysosome : Organell
{
public readonly List<InternalEnzym> enzyms = new List<InternalEnzym>();
private readonly string name;
public Lysosome() : this("Lysosome") { }
public Lysosome(string cellname)
{
name = cellname;
enzyms.Add(new Cathepsin());
enzyms.Add(new GenericLysosomalEnzyme());
enzyms.Add(new LysosomalLipase());
enzyms.Add(new LysosomalNuclease());
enzyms.Add(new LysosomalPhosphatase());
}
public string getName()
{
return name;
}
public void applyChanges(CellRessources Resources, double dt)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ApplyChanges(Resources, dt);
}
}
public void calculateRate(CellRessources res)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ComputeRate(res.Res);
}
}
}
}
+70
View File
@@ -0,0 +1,70 @@
using BaseCellSimulation.Enzyms;
using BaseCellSimulation.Enzyms.Membrane;
using BaseCellSimulation.Enzyms.Membrane.GLUT;
namespace BaseCellSimulation
{
/// <summary>
/// Cell membrane small leakage and passive disposal of waste
/// </summary>
/// <param name="cellname"></param>
/// <param name="glucoseImportRate"></param>
/// <param name="oxygenImportRate"></param>
/// <param name="wasteOuttakeRate"></param>
public class Membrane : Organell
{
public readonly List<MembranEnzyme> enzyms = new List<MembranEnzyme>();
public readonly List<GLUT1> glutTransporters = new List<GLUT1>();
private readonly string name;
public Membrane() : this("Membrane") { }
public Membrane(string cellname)
{
this.name = cellname;
enzyms.Add(new KLeakChannel());
enzyms.Add(new MCT());
enzyms.Add(new NaK_ATPase());
enzyms.Add(new NCX());
enzyms.Add(new PMCA());
// Add GLUT transporters
glutTransporters.Add(new GLUT1());
}
public string getName()
{
return name;
}
public void applyChanges(CellRessources res, double dt)
{
foreach (MembranEnzyme enzyme in enzyms)
{
enzyme.ApplyChanges(res, dt);
}
foreach (GLUT1 glut in glutTransporters)
{
glut.ApplyChanges(res, dt);
}
// --- 5. Kleine Verluste anderer Stoffe (Diffusionslecks) ---
res.Res.Carbon.Glucose = Math.Max(0, res.Res.Carbon.Glucose - 0.001 * dt);
res.Res.Oxygen = Math.Max(0, res.Res.Oxygen - 0.001 * dt);
}
public void calculateRate(CellRessources res)
{
foreach (MembranEnzyme enzyme in enzyms)
{
double gradient = enzyme.CalculateGradient(res);
enzyme.ComputeRate(gradient, res.Env);
}
double glutGradient = glutTransporters[0].CalculateGradient(res);
foreach (GLUT1 glut in glutTransporters)
{
glut.ComputeRate(glutGradient, res.Env);
}
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using BaseCellSimulation.Enzyms;
using BaseCellSimulation.Enzyms.Mytochondrion;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace BaseCellSimulation
{
/// <summary>
/// Powerplant of the cell generates ATP out od NADH and Oxygen
/// </summary>
/// <param name="cellName"></param>
/// <param name="oxPhosVmax"></param>
/// <param name="oxPhosKm"></param>
/// <param name="pO_Ratio"></param>
public class Mitochondrion : Organell
{
public List<Enzym> Enzyms { get; private set; } = new List<Enzym>();
private readonly string name;
public Mitochondrion() : this("Mitochondrion") {}
public Mitochondrion(string cellName)
{
name = cellName;
Enzyms.Add(new PyruvateDehydrogenase());
//Enzyms.Add(new Enzyms.Mytochondrion.ANTTransporter());
Enzyms.Add(new OxPhosEnzyme());
Enzyms.Add(new ATPSynthase());
Enzyms.Add(new TCAEnzyme());
}
public string getName()
{
return name;
}
public void applyChanges(CellRessources Resources, double dt)
{
foreach (Enzym enzym in Enzyms)
{
enzym.ApplyChanges(Resources, dt);
}
}
public void calculateRate(CellRessources res)
{
foreach (Enzym enzym in Enzyms)
{
if (enzym is InternalEnzym internalEnzym)
{
internalEnzym.ComputeRate(res.Res);
}
}
}
}
}
+61
View File
@@ -0,0 +1,61 @@
using BaseCellSimulation.Enzyms;
using BaseCellSimulation.Enzyms.Nucleus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation
{
/// <summary>
/// Cell Core produces RNA uses ATP generates small amount of waste
/// </summary>
/// <param name="cellname"></param>
/// <param name="transcriptionRate"></param>
/// <param name="atpPerNucloide"></param>
public class Nucleus : Organell
{
public List<InternalEnzym> enzyms = new List<InternalEnzym>();
private readonly string name;
public Nucleus() : this("Nucleus") { }
public Nucleus(string cellname)
{
name = cellname;
enzyms.Add(new DNA_Polymerase_Delta());
enzyms.Add(new DNMT1());
enzyms.Add(new HistoneAcetyltransferase());
enzyms.Add(new HistoneDeacetylase());
enzyms.Add(new PARP1());
enzyms.Add(new Topoisomerase_II());
enzyms.Add(new RNA_Polymerase_II());
}
public string getName()
{
return name;
}
public void applyChanges(CellRessources Resources, double dt)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ApplyChanges(Resources, dt);
}
}
public void calculateRate(CellRessources res)
{
foreach (InternalEnzym enzym in enzyms)
{
enzym.ComputeRate(res.Res);
}
}
}
}
+397
View File
@@ -0,0 +1,397 @@
using System;
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();
// 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;
}
}
// --- 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.FBP = 0.005;
cr.Res.Carbon.GAP = 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
{
public double ATP;
public double ADP;
public double AMP;
public double NAD;
public double NADH;
public double GTP;
public double GDP { get; internal set; }
}
/// <summary>Inorganische Phosphate</summary>
public struct Phosphate
{
public double Pi; // anorganisches Phosphat
public double PPi; // Pyrophosphat
}
/// <summary>Kohlenstoff- / Glykolyse-Intermediaten</summary>
public struct CarbonPool
{
public double Glucose;
public double G6P;
public double F6P;
public double FBP;
public double GAP;
public double PBG13;
public double PG3;
public double PG2;
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;
public double NTP;
public double dNTP;
public double mRNA;
public double DNA_damage;
public double AcetylCoA;
public double SAM;
public double MET;
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)
public double ROS; // reactive oxygen species
public double Na;
public double K;
public double H2O2;
}
public struct Cofactor
{
public double B12;
}
public struct Folates
{
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();
}
}
+20
View File
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BaseCellSimulation
{
public struct ValueRange
{
public double Start;
public double End;
public ValueRange(double start, double end)
{
Start = start;
End = end;
}
}
}
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<!--If you are willing to use Windows/MacOS native APIs you will need to create 3 projects.
One for Windows with net9.0-windows TFM, one for MacOS with net9.0-macos and one with net9.0 TFM for Linux.-->
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia.Desktop" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" >
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CellSimulation\CellSimulation.csproj" />
</ItemGroup>
</Project>
+21
View File
@@ -0,0 +1,21 @@
using System;
using Avalonia;
namespace CellSimulation.Desktop;
sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="CellSimulation.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
+42
View File
@@ -0,0 +1,42 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32811.315
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CellSimulation", "CellSimulation\CellSimulation.csproj", "{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CellSimulation.Desktop", "CellSimulation.Desktop\CellSimulation.Desktop.csproj", "{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3DA99C4E-89E3-4049-9C22-0A7EC60D83D8}"
ProjectSection(SolutionItems) = preProject
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseCellSimulation", "BaseCellSimulation\BaseCellSimulation.csproj", "{7C692F24-01D5-47FB-957D-94E170351A05}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.Build.0 = Release|Any CPU
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.Build.0 = Release|Any CPU
{7C692F24-01D5-47FB-957D-94E170351A05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C692F24-01D5-47FB-957D-94E170351A05}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C692F24-01D5-47FB-957D-94E170351A05}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C692F24-01D5-47FB-957D-94E170351A05}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {83CB65B8-011F-4ED7-BCD3-A6CFA935EF7E}
EndGlobalSection
EndGlobal
+15
View File
@@ -0,0 +1,15 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CellSimulation"
x:Class="CellSimulation.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
+54
View File
@@ -0,0 +1,54 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using System.Linq;
using Avalonia.Markup.Xaml;
using CellSimulation.ViewModels;
using CellSimulation.Views;
namespace CellSimulation;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow
{
DataContext = new MainViewModel()
};
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
{
singleViewPlatform.MainView = new MainView
{
DataContext = new MainViewModel()
};
}
base.OnFrameworkInitializationCompleted();
}
private void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

+29
View File
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.Themes.Fluent" />
<PackageReference Include="Avalonia.Fonts.Inter" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="ScottPlot.Avalonia" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BaseCellSimulation\BaseCellSimulation.csproj" />
</ItemGroup>
</Project>
+30
View File
@@ -0,0 +1,30 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using CellSimulation.ViewModels;
namespace CellSimulation;
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
@@ -0,0 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace CellSimulation.ViewModels;
public partial class MainViewModel : ViewModelBase
{
[ObservableProperty]
private string _greeting = "Welcome to Avalonia!";
}
@@ -0,0 +1,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace CellSimulation.ViewModels;
public abstract class ViewModelBase : ObservableObject
{
}
+31
View File
@@ -0,0 +1,31 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:CellSimulation.ViewModels"
xmlns:ScottPlot="clr-namespace:ScottPlot.Avalonia;assembly=ScottPlot.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="CellSimulation.Views.MainView"
x:DataType="vm:MainViewModel">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainViewModel />
</Design.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="4"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ScottPlot:AvaPlot Name="CellPlot"/>
<GridSplitter Grid.Column="1" Background="Black" ResizeDirection="Columns" MinWidth="0"/>
<StackPanel Grid.Column="2" Margin="20">
<TextBlock Margin="0 5">Seconds of Symulation</TextBlock>
<NumericUpDown x:Name="SecondInput" Value="4" Minimum="1"></NumericUpDown>
<TextBlock Margin="0 5">Second Granularity</TextBlock>
<NumericUpDown x:Name="Granularity" Value="0.1" Minimum="0.001" Maximum="0.7"></NumericUpDown>
<Button x:Name="Simulate" Click="StartSimulation" Margin="0 5"> Simulate</Button>
</StackPanel>
</Grid>
</UserControl>
+77
View File
@@ -0,0 +1,77 @@
using Avalonia.Controls;
using BaseCellSimulation;
using ScottPlot;
using ScottPlot.Avalonia;
using System.Collections.Generic;
namespace CellSimulation.Views;
public partial class MainView : UserControl
{
List<cellInfo> cellData = new();
EnviromentState envState = new()
{
Glucose = 5.0, // mM — normaler Blutzuckerwert (~90 mg/dL)
Oxygen = 0.2, // mM — entspricht ca. 5% O2 (physiologischer Bereich)
Waste = 0.0, // mM — initial kein Abfallprodukt
Lactate = 1.0, // mM — basaler Spiegel (wird bei anaerobem Stoffwechsel steigen)
Insulin = 0.05, // µM — basal, kann bei Simulation von Stoffwechselantworten angepasst werden
Protons = 0.00004, // mM — entspricht pH 7.4 (10^-7.4 mol/L)
Na = 140.0, // mM — extrazelluläre Natriumkonzentration
K = 4.5, // mM — extrazelluläre Kaliumkonzentration
Ca = 0.0018
};
public MainView()
{
InitializeComponent();
}
private void StartSimulation(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
Cell cell = new();
cell.EnviromentState = envState;
decimal? granularity = Granularity.Value;
decimal? seconds = SecondInput.Value;
cellData = new();
for (int i = 0; i < seconds/granularity; i++)
{
envState.Glucose += 0.01;
envState.Oxygen += 0.005;
cell.Step((double)granularity);
cellData.Add(cell.GetCellInfo());
}
AvaPlot avaPlot = CellPlot;
avaPlot.Reset();
avaPlot.Plot.Title("Cell Simulation Over Time");
avaPlot.Plot.XLabel("Time (s)");
avaPlot.Plot.YLabel("Concentration / Amount");
var ATP = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.resources["ATP"]).ToArray());
ATP.LegendText = "ATP";
var Glucose = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.resources["Glucose"]).ToArray());
Glucose.LegendText = "Glucose";
var NADH = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.resources["NADH"]).ToArray());
NADH.LegendText = "NADH";
var NAD = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.resources["NAD"]).ToArray());
NAD.LegendText = "NAD";
var AminoAcids = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.resources["AminoAcids"]).ToArray());
AminoAcids.LegendText = "AminoAcids";
var CytosolicCa = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.caState.CytosolicCa).ToArray());
CytosolicCa.LegendText = "Cytosolic Ca";
var ER_Ca = avaPlot.Plot.Add.Scatter(cellData.ConvertAll(c => c.time).ToArray(), cellData.ConvertAll(c => c.caState.ER_Ca).ToArray());
ER_Ca.LegendText = "ER Ca";
avaPlot.Plot.Legend.Orientation = Orientation.Horizontal;
avaPlot.Plot.ShowLegend(Edge.Bottom);
avaPlot.Refresh();
}
}
+12
View File
@@ -0,0 +1,12 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:CellSimulation.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:CellSimulation.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="CellSimulation.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="CellSimulation">
<views:MainView />
</Window>
+11
View File
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace CellSimulation.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
+21
View File
@@ -0,0 +1,21 @@
<Project>
<!-- https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<!-- Avalonia packages -->
<!-- Important: keep version in sync! -->
<PackageVersion Include="Avalonia" Version="11.3.6" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.6" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.6" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
<PackageVersion Include="Avalonia.iOS" Version="11.3.6" />
<PackageVersion Include="Avalonia.Browser" Version="11.3.6" />
<PackageVersion Include="Avalonia.Android" Version="11.3.6" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="ScottPlot.Avalonia" Version="5.1.57" />
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.15" />
</ItemGroup>
</Project>