private void RunSimulation() { // For simple simulations, just use the simulator class. // Interact with the HHModel directly (like this) only if you want to do a lot of tweaking. Stopwatch stopwatch = Stopwatch.StartNew(); double stepSizeMsec = .01; double sampleRate = 1.0 / stepSizeMsec; double simulationLengthMsec = (double)nudDurationMs.Value; int pointCount = (int)(simulationLengthMsec / stepSizeMsec); double[] voltage = new double[pointCount]; double[] stateH = new double[pointCount]; double[] stateM = new double[pointCount]; double[] stateN = new double[pointCount]; double[] INa = new double[pointCount]; double[] IK = new double[pointCount]; double[] IKleak = new double[pointCount]; double[] stimulus = GenerateStimulusWaveform(pointCount); var hh = new HHModel { ENa = (double)nudENa.Value, EK = (double)nudEK.Value, EKleak = (double)nudEKLeak.Value, gNa = (double)nudGNa.Value, gK = (double)nudGK.Value, gKleak = (double)nudGKLeak.Value, Cm = (double)nudCm.Value }; for (int i = 0; i < pointCount; i++) { hh.StepForward(stimulus[i], stepSizeMsec); voltage[i] = hh.Vm; stateH[i] = hh.h.activation; stateM[i] = hh.m.activation; stateN[i] = hh.n.activation; INa[i] = hh.INa; IK[i] = hh.IK; IKleak[i] = hh.IKleak; } double elapsedSec = (double)stopwatch.ElapsedTicks / Stopwatch.Frequency; string message = string.Format("Simulated {2:n0} time points\nin {0:0.00} ms ({1:0.00} Hz)", elapsedSec * 1000.0, 1 / elapsedSec, pointCount); rtbStatus.Text = message; formsPlot1.plt.Title("Membrane Potential (Vm)"); formsPlot1.plt.YLabel("Potential (mV)"); formsPlot1.plt.Clear(); formsPlot1.plt.PlotSignal(voltage, sampleRate, yOffset: -70, color: Color.Blue); formsPlot1.plt.AxisAuto(); formsPlot1.Render(); formsPlot3.plt.Title("Stimulus"); formsPlot3.plt.YLabel("Current (µA/cm²)"); formsPlot3.plt.Clear(); formsPlot3.plt.PlotSignal(stimulus, sampleRate, color: Color.Red); formsPlot3.plt.AxisAuto(); formsPlot3.Render(); formsPlot2.plt.Clear(); if (rbDisplayActivity.Checked == true) { formsPlot2.plt.Title("Voltage-Dependent Gate Activation"); formsPlot2.plt.YLabel("Activation (frac)"); formsPlot2.plt.PlotSignal(stateH, sampleRate, label: "h"); formsPlot2.plt.PlotSignal(stateM, sampleRate, label: "m"); formsPlot2.plt.PlotSignal(stateN, sampleRate, label: "n"); } else if (rbDisplayCurrent.Checked == true) { formsPlot2.plt.Title("Channel Current"); formsPlot2.plt.YLabel("Current (µA/cm²)"); formsPlot2.plt.PlotSignal(INa, sampleRate, label: "VGSC"); formsPlot2.plt.PlotSignal(IK, sampleRate, label: "VGKC"); formsPlot2.plt.PlotSignal(IKleak, sampleRate, label: "Kleak"); } else { throw new NotImplementedException(); } formsPlot2.plt.XLabel("Simulation Time (milliseconds)"); formsPlot2.plt.Legend(); formsPlot2.plt.AxisAuto(); formsPlot2.Render(); }