Experimental methods

Note

This documentation is work in progress. Currently, the extension of Documenter.jl in my package MoST.jl is still experimental. As the package evolves further, this documentation will increase in readability.

InaMo.ExperimentalMethods

This package contains models that capture experimental methods such as voltage and current clamp protocols, which can be used to measure current or voltage behavior of full cells or individual components.

The methods in this package mainly consist of three base modules: CurrentClamp for current clamp experiments, VoltageClamp for voltage clamp experiments and TestPulses for determining pulse protocols for either type of experiment.

Base classes

InaMo.ExperimentalMethods.Interfaces.TestPulses

This model generates a pulse_signal that stays zero for d_hold seconds and then switches to one for a duration of d_pulse, repeating the cycle with another zero period of d_hold seconds and another pulse of d_pulse seconds.

The pulse_signal can be used to facilitate building pulse protocols by simply using the formula x = x_hold + pulse_signal * (x_pulse - x_hold) where x is the resulting pulse signal and x_hold is the value of x during the holding period and x_pulse is the value of x during the pulse.

model TestPulses "generic component to generate a dimensionless pulse signal"
  parameter SI.Duration d_hold = 2 "holding period";
  parameter SI.Duration d_pulse = 0.050 "pulse period";
  output Boolean pulse_start = sample(d_hold, d_hold + d_pulse) "signals start of pulse";
  output Boolean pulse_end = sample(d_hold + d_pulse, d_hold + d_pulse) "signals end of pulse";
  output Integer pulse_signal(start = 0, fixed = true) "0 during holding period, 1 during pulse";
equation
  when pulse_start then
    pulse_signal = 1;
  elsewhen pulse_end then
    pulse_signal = 0;
  end when;
  annotation(
    Documentation(info = "<html>
    <p>
      This model generates a pulse_signal that stays zero for d_hold seconds
      and then switches to one for a duration of d_pulse, repeating the cycle
      with another zero period of d_hold seconds and another pulse of d_pulse
      seconds.
    </p>
    <p>
      The pulse_signal can be used to facilitate building pulse protocols by
      simply using the formula x = x_hold + pulse_signal * (x_pulse - x_hold)
      where x is the resulting pulse signal and x_hold is the value of x
      during the holding period and x_pulse is the value of x during the pulse.
    </p>
  </html>"),
    Icon(graphics = {Line(origin = {-55.7024, -80.0376}, points = {{-40.2575, -14}, {-20.2575, -14}, {-20.2575, 14}, {-16.2575, 14}, {-16.2575, -14}, {-0.257485, -14}, {-0.257485, 14}, {3.74251, 14}, {3.74251, -14}, {19.7425, -14}, {19.7425, 14}, {23.7425, 14}, {23.7425, -14}, {37.7425, -14}}, color = {0, 0, 255})}));
end TestPulses;

Voltage clamp methods

InaMo.ExperimentalMethods.VoltageClamp.VoltageClamp

Simple voltage clamp model.

The positive pin of this component represents the extracellular electrode while the negative pin represents the intracellular electrode(s).

A positive value for v_stim leads to a positive outward voltage.

model VoltageClamp "general voltage clamp model"
  extends InaMo.Currents.Interfaces.TwoPinVertical;
  extends InaMo.Icons.CurrentClamp;
  Modelica.Electrical.Analog.Sources.SignalVoltage stim(v = v_stim) "stimulation model inducing input voltage into circuit";
  Modelica.Electrical.Analog.Basic.Ground g "ground electrode";
  SI.Voltage v_stim "input voltage (needs to be defined externally)";
  SI.Current i(nominal = 1e-12) = -stim.i "measured membrane current";
equation
  connect(p, stim.p);
  connect(n, stim.n);
  connect(stim.n, g.p);
  annotation(
    Documentation(info = "<html>
  <p>Simple voltage clamp model.</p>
  <p>The positive pin of this component represents the extracellular electrode
  while the negative pin represents the intracellular electrode(s).</p>
  <p>A positive value for v_stim leads to a positive outward voltage.</p>
  </html>"),
    Icon(graphics = {Text(origin = {57, -68}, extent = {{-27, 18}, {43, -32}}, textString = "V")}));
end VoltageClamp;

InaMo.ExperimentalMethods.VoltageClamp.VCTestPulses

model VCTestPulses "voltage clamp that sends periodic test pulses"
  extends VoltageClamp;
  extends InaMo.ExperimentalMethods.Interfaces.TestPulses;
  parameter SI.Voltage v_hold = -0.090 "voltage during holding period";
  discrete input SI.Voltage v_pulse "voltage during pulse (must be defined externally)";
equation
  v_stim = pulse_signal * (v_pulse - v_hold) + v_hold;
end VCTestPulses;

InaMo.ExperimentalMethods.VoltageClamp.VCTestPulsesPeak

Ths model extends VCTestPulses with the capability to capture three different types of peak currents:

  • "peak": The peak current achieved between pulse_start and pulse_end, i.e. during the pulse
  • "tail": The peak current achieved between pulse_end and the next pulse_start, i.e. after the pulse
  • "end": The current achieved at pulse_end

The word "peak" in these descriptions refers to the farthest distance to zero achieved during the respective time period. This can either be the global maximum or the global minimum.

Consequently, all three current measures (is_peak, is_tail, and is_end) capture the information of the last pulse cycle. is_end and is_peak are updated at pulse_end and is_tail is updated at pulse_start.

For plotting convenience, the variables vs_peak, vs_tail, and vs_end capture the voltages of the pulse associated with the current measurement in is_peak, is_tail, and is_end respectively. A parametric current-voltage plot then becomes possible by just plotting a pair like (is_peak, vs_peak) without having to process the simulation output.

model VCTestPulsesPeak "voltage clamp with test pulse protocol and peak capture"
  extends VCTestPulses;
  discrete SI.Current is_peak(start = 0, fixed = true, nominal = 1e-12) "steady step function of peak current during last pulse";
  discrete SI.Current is_tail(start = 0, fixed = true, nominal = 1e-12) "steady step function of peak tail current after last pulse";
  discrete SI.Current is_end(start = 0, fixed = true, nominal = 1e-12) "steady step function of current at end of last pulse";
  discrete SI.Voltage vs_peak(start = 0, fixed = true) "steady step function of pulse associated with is_peak";
  discrete SI.Voltage vs_end(start = 0, fixed = true) "steady step function of pulse associated with is_end";
  discrete SI.Voltage vs_tail(start = 0, fixed = true) "steady step function of pulse associated with is_tail";
protected
  discrete SI.Current peak_i(start = 0, fixed = true, nominal = 1e-12) "peak current during pulse";
  discrete SI.Current tail_i(start = 0, fixed = true, nominal = 1e-12) "peak current after pulse";
  Boolean peak_indicator(start = false, fixed = true) = der(i) * 1e12 < 0 "forces event at peak (factor of 1e12 is required to detect zero crossing)";
  discrete SI.Time tp_last(start = 0, fixed = true) "time stamp of start of last pulse";
  discrete SI.Voltage vp_last(start = 0, fixed = true) "voltage of last pulse";
  Boolean within_pulse = time - pre(tp_last) < d_pulse "true during pulse";
  Boolean after_pulse = time - pre(tp_last) > d_pulse "true after pulse has passed";

  function absmax "returns input whose absolute value is larger, preserving the sign"
    input Real a "first input";
    input Real b "second input";
    output Real m "a if abs(a) > abs(b), otherwise b";
  algorithm
    m := if abs(a) > abs(b) then a else b;
  end absmax;
equation
  when pulse_start then
    peak_i = i;
  elsewhen change(peak_indicator) and within_pulse or pulse_end then
    peak_i = absmax(i, pre(peak_i));
  end when;
  when pulse_end then
    tail_i = i;
  elsewhen change(peak_indicator) and after_pulse or pulse_end then
    tail_i = absmax(i, pre(tail_i));
  end when;
  when pulse_start then
    is_tail = pre(tail_i);
    vs_tail = pre(vp_last);
    tp_last = time;
    vp_last = v_pulse;
  end when;
  when pulse_end then
    is_end = pre(i);
    is_peak = pre(peak_i);
    vs_end = vp_last;
    vs_peak = vs_end;
  end when;
  annotation(
    Documentation(info = "<html>
  <p>Ths model extends VCTestPulses with the capability to capture three
  different types of peak currents:</p>
  <ul>
    <li>&quot;peak&quot;: The peak current achieved between pulse_start and
      pulse_end, i.e. <i>during</i> the pulse</li>
    <li>&quot;tail&quot: The peak current achieved between pulse_end and the
      next pulse_start, i.e. <i>after</i> the pulse</li>
    <li>&quot;end&quot;: The current achieved at pulse_end</li>
  </ul>
  <p>The word &quot;peak&quot; in these descriptions refers to the farthest
  distance to zero achieved during the respective time period.
  This can either be the global maximum or the global minimum.</p>
  <p>Consequently, all three current measures (is_peak, is_tail, and is_end)
    capture the information of the last pulse cycle.
    is_end and is_peak are updated at pulse_end and is_tail is updated at
    pulse_start.</p>
  <p>For plotting convenience, the variables vs_peak, vs_tail, and vs_end
    capture the voltages of the pulse associated with the current measurement
    in is_peak, is_tail, and is_end respectively.
    A parametric current-voltage plot then becomes possible by just plotting
    a pair like (is_peak, vs_peak) without having to process the simulation
    output.</p>
</html>"));
end VCTestPulsesPeak;

Current clamp methods

InaMo.ExperimentalMethods.CurrentClamp.CurrentClamp

Simple current clamp model.

The positive pin of this component represents the extracellular electrode while the negative pin represents the intracellular electrode(s).

A positive value for i_stim leads to a positive outward current.

To measure the voltage in the circuit, the variable v can be used, which is introduced through the base class TwoPinVertical.

model CurrentClamp "current clamp that defines input current to measure voltage response"
  extends InaMo.Currents.Interfaces.TwoPinVertical;
  extends InaMo.Icons.CurrentClamp;
  Modelica.Electrical.Analog.Sources.SignalCurrent stim(i = i_stim) "stimulation model inducing input current into circuit";
  Modelica.Electrical.Analog.Basic.Ground g "ground electrode";
  SI.Current i_stim "input current (needs to be defined externally)";
equation
  connect(p, stim.p);
  connect(n, stim.n);
  connect(stim.n, g.p);
  annotation(
    Documentation(info = "<html>
  <p>Simple current clamp model.</p>
  <p>The positive pin of this component represents the extracellular electrode
  while the negative pin represents the intracellular electrode(s).</p>
  <p>A positive value for i_stim leads to a positive outward current.</p>
  <p>To measure the voltage in the circuit, the variable v can be used, which
  is introduced through the base class TwoPinVertical.</p>
  </html>"),
    Icon(graphics = {Text(origin = {57, -68}, extent = {{-27, 18}, {43, -32}}, textString = "I")}));
end CurrentClamp;

InaMo.ExperimentalMethods.CurrentClamp.CCTestPulses

model CCTestPulses "current clamp that sends periodic test pulses"
  extends CurrentClamp;
  extends InaMo.ExperimentalMethods.Interfaces.TestPulses;
  parameter SI.Current i_hold = 0 "current during holding period";
  // FIXME cannot be discrete in OpenModelica, but should be
  input SI.Current i_pulse "current during pulse (must be defined externally)";
equation
  i_stim = pulse_signal * (i_pulse - i_hold) + i_hold;
end CCTestPulses;