Skip to content
Snippets Groups Projects
Commit 5a95fd0c authored by Tim De Coster's avatar Tim De Coster
Browse files

APqr8 fully commented

parent e76327dc
No related branches found
No related tags found
No related merge requests found
......@@ -409,27 +409,34 @@ OUT:
*/
void gAPqr7::initParameters()
{
// system related parameters
systime = 0;
period = RT::System::getInstance()->getPeriod() * 1e-6; // ms
// cell related parameters
Vm = -80; // mV
Cm = 150; // pF
Rm = 150; // MOhm
// upstroke related parameters
slope_thresh = 5.0; // mV
corr = 1;
Iout = 0; // pA
output(0) = -Iout * 0.5e-3;
period = RT::System::getInstance()->getPeriod() * 1e-6; // ms
systime = 0;
count = 0;
V_cutoff = -40; // mV
// logging parameters
log_ideal_on = 0;
lognum = 3;
APs = -1;
count2 = 0;
// correction parameters
act = 0;
corr = 1;
noise_tresh = 0.5; // mV
Rm_corr_up=8;
Rm_corr_down=2;
noise_tresh = 0.5; // mV
// standard loop parameters
count = 0;
enter = 0;
BCL = 0; // ms
count2 = 0;
APs = -1;
V_cutoff = -40; // mV
BCL_cutoff = 0.98;
enter = 0;
log_ideal_on = 0;
lognum = 3;
modulo = (1.0/(RT::System::getInstance()->getPeriod() * 1e-6)) * 1000.0;
Iout = 0; // pA
output(0) = -Iout * 0.5e-3;
}
......@@ -58,7 +58,6 @@ class gAPqr7 : public DefaultGUIModel
double lognum;
double APs;
long long count2;
double iAP;
// correction parameters
double act;
int corr;
......
......@@ -16,11 +16,6 @@
*/
/*
This version logs 3 APs and starts correcting the 4th AP and onwards, using an LED light source connected to output(0), if the AP becomes longer then the average of the 3 that has been recorded.
*/
#include <APqr8.h>
#include <math.h>
#include <vector>
......@@ -85,7 +80,6 @@ STATE: non-modifiable variable in the code
static DefaultGUIModel::variable_t vars[] = {
{ "Vm (mV)", "Membrane potential (mV)", DefaultGUIModel::INPUT, },
{ "Iout (pA)", "Output current (pA)", DefaultGUIModel::OUTPUT, },
{ "iAP", "ideal AP", DefaultGUIModel::OUTPUT, },
{ "Cm (pF)", "pF", DefaultGUIModel::PARAMETER
| DefaultGUIModel::DOUBLE, },
{ "V_cutoff (mV)", "Threshold potential for the detection of the beginning of an AP, together with Slope_thresh", DefaultGUIModel::PARAMETER | DefaultGUIModel::DOUBLE, },
......@@ -105,19 +99,11 @@ static DefaultGUIModel::variable_t vars[] = {
| DefaultGUIModel::DOUBLE, },
{ "Correction (0 or 1)", "Switch Rm correction off (0) or on (1)",
DefaultGUIModel::PARAMETER | DefaultGUIModel::DOUBLE, },
{ "Vm2 (mV)", "Membrane potential (mV)", DefaultGUIModel::STATE, },
{ "Iout2 (pA)", "Output Current (pA)", DefaultGUIModel::STATE, },
{ "Period (ms)", "Period (ms)", DefaultGUIModel::STATE, },
{ "Time (ms)", "Time (ms)", DefaultGUIModel::STATE, },
{ "APs2", "APs", DefaultGUIModel::STATE, },
{ "log_ideal_on2", "log_ideal_on", DefaultGUIModel::STATE, },
{ "BCL2", "BCL", DefaultGUIModel::STATE, },
{ "enter2", "enter", DefaultGUIModel::STATE, },
{ "Rm2 (MOhm)", "MOhm", DefaultGUIModel::STATE, },
{ "act2", "0 or 1", DefaultGUIModel::STATE, },
{ "count", "number", DefaultGUIModel::STATE, },
{ "count2", "number", DefaultGUIModel::STATE, },
{ "modulo_state", "number", DefaultGUIModel::STATE, },
{ "Period (ms)", "Period (ms)", DefaultGUIModel::STATE, }, // To check that the period taken by the algorithm is the same as the one i nthe control panel module
{ "Time (ms)", "Time (ms)", DefaultGUIModel::STATE, }, // To check that the algorithm is running
{ "APs2", "APs", DefaultGUIModel::STATE, }, // To check whether APs are being logged and the counter increases
{ "BCL2", "BCL", DefaultGUIModel::STATE, }, // To check what the eventual BCL of the ideal AP has become. You can see then if the APs were logged correctly
{ "act2", "0 or 1", DefaultGUIModel::STATE, }, // Switches from 0 to 1 and back continuously as a check to see whether you are computing error values and corrected values
};
/*
......@@ -274,41 +260,67 @@ void gAPqr8::execute(void)
// *************************************************
if (act == 1)
{
Iout = Cm * (1/Rm) * (Vm - ideal_AP[count]);
if (Iout < 0){Iout = 0;}
if (Iout > 5){Iout = 5;}
output(0) = Iout;
Vm_diff_log[count] = Vm - ideal_AP[count];
iAP = ideal_AP[count]/1000;
output(1) = iAP;
// This statement is entered whenever the instruction to correct the AP has
// been given.
Iout = Cm * (1/Rm) * (Vm - ideal_AP[count]); // Calculate the outward going current as
// a value proportional to capacitance,
// conductivity (1/resistance), and the error
if (Iout < 0){Iout = 0;} // Set the ouput to 0 whenever you cannot correct in the direction
// the channelrhodopsin pushes the membrane potential
if (Iout > 5){Iout = 5;} // The maximal LED driver output is 5V
output(0) = Iout; // This is equal to Vout and will drive the LED
Vm_diff_log[count] = Vm - ideal_AP[count]; // Log the errors
}
// **************************************
// **************************************
// ** Updating the necessary variables **
// **************************************
// **************************************
if(corr == 1 && act == 1 && count > 1 && abs(Vm_diff_log[count])>noise_tresh)
{
if((Vm_diff_log[count-1] / Vm_diff_log[count]) < 0) //they have the opposite sign, so an overshoot occured
// This statement is entered whenever an update is needed in the resistance.
// The if conditions measure the following:
// 1) Whether correction adaptation is on
// 2) Whether currently there is correction going on
// 3) whether we are not in the very first step (gives errors)
// 4) whether the current error is larger than the noise threshold
if((Vm_diff_log[count-1] / Vm_diff_log[count]) < 0)
{
Rm = Rm * Rm_corr_up;
// This statement is entered whenever two consecutive error values have
// an opposite sign. This means that an overshoot in correction occurred.
// Therefore Iout should become less, and hence Rm should be increased.
Rm = Rm * Rm_corr_up; // Increase the resistance
}
if(abs(Vm_diff_log[count-1]) < abs(Vm_diff_log[count]) && (Vm_diff_log[count-1] / Vm_diff_log[count]) > 0) //the difference is getting larger, so increase current
if(abs(Vm_diff_log[count-1]) < abs(Vm_diff_log[count]) && (Vm_diff_log[count-1] / Vm_diff_log[count]) > 0 && Rm >= 0.01*Rm_corr_down)
{
Rm = Rm / Rm_corr_down;
// This statement is entered whenever two consecutive error values have
// the same sign, and when the error values increase in value. This means
// that the error is increasing. Hence we need to correct stronger and Iout
// should increase. As a consequence the resistance Rm should be decreased.
// However, a lower bounds is put on Rm to prevent the updated Rm value from
// reaching infinity.
Rm = Rm / Rm_corr_down; // Decrease the resistance
}
}
if (count > BCL_cutoff*BCL)
{
act = 0;
output(0) = 0;
}
count++;
// This statement is entered whenever the end of an AP is reached.
// The if condition measures the following:
// 1) Whether the current AP is further than a chosen cutoff of the pre-determined basic cycle length
count_r = (double)count/1000.0;
count2_r = (double)count2/1000.0;
act = 0; // Stop correcting during the last phase of the AP (is RMP)
output(0) = 0; // Send a 0 output since the last output is otherwise kept
}
count++; // End of the real-time loop, adjust the counter
}
/*
......@@ -343,19 +355,11 @@ void gAPqr8::update(DefaultGUIModel::update_flags_t flag)
setParameter("BCL_cutoff (pct)", BCL_cutoff);
setParameter("Slope_thresh (mV/ms)", slope_thresh);
setParameter("Correction (0 or 1)", corr);
setState("Vm2 (mV)", Vm);
setState("Iout2 (pA)", Iout);
setState("Time (ms)", systime);
setState("Period (ms)", period);
setState("APs2", APs);
setState("log_ideal_on2", log_ideal_on);
setState("BCL2", BCL);
setState("enter2", enter);
setState("Rm2 (MOhm)", Rm);
setState("act2", act);
setState("count", count_r);
setState("count2", count2_r);
setState("modulo_state", modulo);
break;
case MODIFY:
Cm = getParameter("Cm (pF)").toDouble();
......@@ -418,7 +422,6 @@ void gAPqr8::initParameters()
systime = 0;
count = 0;
act = 0;
iAP=0;
Rm_corr_up=2;
Rm_corr_down=2;
noise_tresh = 2; // mV
......@@ -430,7 +433,5 @@ void gAPqr8::initParameters()
enter = 0;
log_ideal_on = 0;
lognum = 3;
count_r = 0;
count2_r = 0;
modulo = (1.0/(RT::System::getInstance()->getPeriod() * 1e-6)) * 1000.0;
}
......@@ -35,35 +35,41 @@ class gAPqr8 : public DefaultGUIModel
virtual void update(DefaultGUIModel::update_flags_t);
private:
// functions
void cleanup();
int i;
void initParameters();
double Vm;
// system related parameters
double systime;
double period;
// arrays
double Vm_log[10000] = {0};
double ideal_AP[10000] = {0};
double Vm_diff_log[10000] = {0};
// cell related parameters
double Vm;
double Cm;
double Rm;
// Upstroke related parameters
double slope_thresh;
double Iout;
double systime;
double count_r;
double count2_r;
long long count;
double Vm_log[10000] = {0};
double ideal_AP[10000] = {0};
long long count2;
double enter;
double BCL;
double BCL_cutoff;
double noise_tresh;
double V_cutoff;
// logging parameters
double log_ideal_on;
double lognum;
double APs;
long long count2;
// correction parameters
double act;
double Vm_diff_log[10000] = {0};
int corr;
double iAP;
double noise_tresh;
double Rm_corr_up;
double Rm_corr_down;
double lognum;
// standard loop parameters
long long count;
double enter;
double BCL;
double BCL_cutoff;
double modulo;
int i;
double Iout;
};
......@@ -29,6 +29,46 @@
#include <math.h>
#include <vector>
/*
************
* APqrPID3 *
************
This software provides an Action Potential Cure (APqr) to correct divergent
membrane potentials in excitable biological systems. The first X action
potentials are logged when the software starts, after which AP correction
starts from the (X+1)-st AP onwards. This correction occurs with the use of
LED-controlled illumination on optogenetically modified cells.
IN:
*) Cm Capacitance of the cell
*) V_cutoff Threshold potential for the detection of the beginning
of an AP
*) Slope_tresh Slope threshold that defines the beginning of the
AP (mV/ms)
*) BCL_cutoff Threshold value for the end of an AP, given as a
percentage of the total APD
*) lognum Number of APs that need to be logged as a reference
*) Rm Initial resistance
*) Rm_corr_up Factor to increase Rm with when necessary
*) Rm_corr_down Factor to decrease Rm with when necessary
*) noise_tresh The noise level that is allowed around the ideal value
before correcting
OUT:
*) Vout voltage that is used to inject the calculated amount
of current into the excitable system
*/
/*
createRTXIPlugin
----------------
Creation of a new RTXI Plugin
IN:
*) None
OUT:
*) RTXIPlugin
*/
extern "C" Plugin::Object *createRTXIPlugin(void)
{
return new gAPqrPID3();
......@@ -67,7 +107,7 @@ static DefaultGUIModel::variable_t vars[] = {
DefaultGUIModel::PARAMETER | DefaultGUIModel::DOUBLE, },
{ "min_PID", "value under which the lights get switched off",
DefaultGUIModel::PARAMETER | DefaultGUIModel::DOUBLE, },
{ "reset_I_on", "value that indicates whetehr or ont to reset I at RMP",
{ "reset_I_on", "value that indicates whetehr or not to reset I at RMP",
DefaultGUIModel::PARAMETER | DefaultGUIModel::DOUBLE, },
{ "Vm2 (mV)", "Membrane potential (mV)", DefaultGUIModel::STATE, },
{ "P", "P term", DefaultGUIModel::STATE, },
......@@ -86,8 +126,25 @@ static DefaultGUIModel::variable_t vars[] = {
{ "modulo_state", "number", DefaultGUIModel::STATE, },
};
/*
num_vars
--------
variable denoting the amount of variables that is displayed in the GUI
*/
static size_t num_vars = sizeof(vars) / sizeof(DefaultGUIModel::variable_t);
/*
gAPqrPID3
------
This function constructs the actual GUI by basing itself on the Default GUI Model.
It creates a module with a name, initializes the GUI, initializes the parameters,
adds a refresh, and allows you to resize.
IN:
*) None
OUT:
*) None
*/
gAPqrPID3::gAPqrPID3(void) : DefaultGUIModel("APqrPID3", ::vars, ::num_vars)
{
setWhatsThis(
......@@ -99,17 +156,25 @@ gAPqrPID3::gAPqrPID3(void) : DefaultGUIModel("APqrPID3", ::vars, ::num_vars)
resizeMe();
}
gAPqrPID3::~gAPqrPID3(void)
{
}
gAPqrPID3::~gAPqrPID3(void){}
/*
cleanup
-------
The APqr software makes use of three list structures which need cleaning after
a reset of parameters. The cleanup function takes care of this.
IN:
*) None
OUT:
*) None
*/
void gAPqrPID3::cleanup()
{
for(i=0;i<10000;i++){
Vm_log[i]=0;
Vm_diff_log[i]=0;
ideal_AP[i]=0;
}
}
......@@ -163,37 +228,81 @@ double gAPqrPID3::sumx2(double period, double length)
void gAPqrPID3::execute(void)
{
systime = count * period; // time in milli-seconds
Vm = input(0) * 1e2; // convert 10V to mV. Divided by 10 because the amplifier produces 10-fold amplified voltages. Multiplied by 1000 to convert V to mV.
Vm_log[count % (int)modulo] = Vm;
// Part of the code to create the ideal AP from the first three beats.
systime = count * period; // time in milli-seconds
Vm = input(0) * 1e2; // convert 10V to mV. Divided by 10 because
// the amplifier produces 10-fold amplified
// voltages. Multiplied by 1000 to convert
// V to mV.
Vm_log[count % (int)modulo] = Vm; // Logging the measured Vm in a list
// where the modulo component makes
// sure you keep cycling when you have
// reached the maximum number in the list.
// ****************************
// ****************************
// ** Recording the ideal AP **
// ****************************
// ****************************
if(count>(int)(1/period)-1 && (Vm - Vm_log[(count-(int)(1/period)) % (int)modulo]) >= slope_thresh && APs<lognum && enter == 0 && Vm > V_cutoff)
{
BCL = (APs==-1? 0: (BCL*APs + count2)/(APs+1));
log_ideal_on = 1;
count2 = 0;
enter = 1;
APs++;
// This statement is entered whenever an upstroke is detected and the amount of
// recorded APs is smaller than lognum.
// The if conditions measure the following:
// 1) Whether you are far enough in the recording such that you don't accidentaly
// start in an ongoing AP
// 2) Whether two consecutive measuring points show a large enough slope that can
// be identified with an upstroke
// 3) Whether less than lognum APs were recorded
// 4) Whether you are currently not in an action potential
// 5) Whether the mesured voltage is above a voltage treshold
BCL = (APs==-1? 0: (BCL*APs + count2)/(APs+1)); // Rolling average of the basic cycle length
log_ideal_on = 1; // Switches on logging the AP
count2 = 0; // Resets the logging counter
enter = 1; // Switches on the indicator that an AP has started
APs++; // Counts the AP upstrokes that have passed
}
if((Vm - Vm_log[(count-(int)(1/period)) % (int)modulo]) < 0 && enter == 1)
{
enter = 0;
// This statement is entered whenever the upstroke phase of an AP is over.
// The if conditions measure the following:
// 1) Whether two consecutive measuring points show a negative slope
// 2) Whether you currently are in an ongoing AP
enter = 0; // Switches off the indicator that an AP has started
}
if(APs<lognum && log_ideal_on == 1)
{
ideal_AP[count2] = (ideal_AP[count2]*APs + Vm)/(APs+1);
count2++;
// This statement is entered whenever logging of the AP is on
// The if conditions measure the following:
// 1) Whether less than lognum APs were recorded
// 2) Whether the AP should be logged
ideal_AP[count2] = (ideal_AP[count2]*APs + Vm)/(APs+1); // Rolling average of the AP values
count2++; // Increasing the logging counter
}
// Part of the code that resets the counter once a new AP is detected
// ****************************
// ****************************
// ** Detecting AP upstrokes **
// ****************************
// ****************************
if (act == 0 && (Vm - Vm_log[(count-(int)(1/period)) % (int)modulo]) >= slope_thresh && APs >= lognum && Vm > V_cutoff)
{
count = 0;
act = 1;
// This statement is entered whenever an upstroke is detected after the
// ideal APs have been recorded.
// The if conditions measure the following:
// 1) Whether currently nothing is being done or corrected
// 2) Whether two consecutive measuring points show a large enough slope that can
// be identified with an upstroke
// 3) Whether lognum APs were already recorded before
// 4) Whether the mesured voltage is above a voltage treshold
count = 0; // Reset the correction counter
act = 1; // Switch the correction on
}
// Part of the code that implements the PID
......@@ -285,6 +394,23 @@ void gAPqrPID3::execute(void)
}
/*
Update
------
This function updates the parameters of the code depending on the flag that is
given to it, where each flag is associated to a button.
INIT: associated to the loading of the module
MODIFY: associated to the Modify button
PERIOD: associated to the period linker with the "system control panel" module
PAUSE: associate to the pause button when pressing on it
UNPAUSE: associated to the pause button when unpressing it
IN:
*) flag Indicating the state of the update:
INIT, MODIFY, PERIOD, PAUSE, UNPAUSE
OUT:
*) None
*/
void gAPqrPID3::update(DefaultGUIModel::update_flags_t flag)
{
switch (flag)
......@@ -367,6 +493,17 @@ void gAPqrPID3::update(DefaultGUIModel::update_flags_t flag)
}
}
/*
initParameters
--------------
This function sets all values to their defaults when no external parameters are provided
through the GUI interface.
IN:
*) None
OUT:
*) None
*/
void gAPqrPID3::initParameters()
{
Vm = -80; // mV
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment