/* This file contains functions to implement various aspects of common lab protocols Such as 0Na perfusion (set Na channels to 0), TEA electrodes, voltage clamp steps, ramps .. currently a work in progress. Many aspects of this are untested with the Hines solver (by me, at least), so use caution. -Damon Lamb */ /* Function createChirp creates a source which outputs a Chirp protocol loaded from the specified file the chirp data points in the file are presumed to be from -1 to 1, or a p-p amplitude of 2, for 60 seconds at steps of 2^-14. note: could change to a variable time step, but a fixed assumption helps prevent some silly user errors. */ function createChirp(chirpfile, amplitude) str chirpfile float amplitude echo "Creating chirp from: " {chirpfile} " with amplitude " {amplitude} create table /chirpsource create neutral /chirpsource/amplitude create calculator /chirpsource/scaled setfield /chirpsource step_mode 1 stepsize 0 // step_mode 1: loop acts as function generator, step by main clock time step //setfield /chirpsource step_mode 0 stepsize 0 // step_mode 0: IO - calculates based on PRD for each step, step by main clock time step call /chirpsource TABCREATE 983041 0 60 // source data is in steps of 2^-14 from 0 to 60 seconds file2tab {chirpfile} /chirpsource table -xy 983041 // one additional time step to include both 0 and 60 setfield /chirpsource/amplitude x {amplitude/2} //addmsg /chirpsource/amplitude /chirpsource PRD x //does not work addmsg /chirpsource/amplitude /chirpsource/scaled MULTIPLY x addmsg /chirpsource/ /chirpsource/scaled MULTIPLY output setfield /chirpsource/scaled output_init 1 //call /chirpsource/scaled PROCESS -> this gets undone by reset, must call later after final reset end /* createCC(compartment) Creates the base elements for the ramp and pulse protocols. */ function createCC // create pulsegen and calculator for step and ramp protocols create pulsegen /pgen // for step protocols _--_ create calculator /rampgen // for ramp protocols _/\_ create neutral /rampgen/istep // for ramp protocols _/\_ end /* Function initpgenCC initializes messages from a pulsegen object to inject current into the given compartment (typically soma) Takes the following argument str compartment : compartment to inject current into (typically soma) e.g.: initstepsCC /HE12_sync/soma */ function initpgenCC(compartment) str compartment //connects pulsegenator to the compartment echo "Creating message from /pgen to" {compartment} addmsg /pgen {compartment} INJECT output end /* Function initrampgenCC initializes messages from a rampgen object to inject current into the given compartment (typically soma) Takes the following argument str compartment : compartment to inject current into (typically soma) e.g.: initstepsCC /HE12_sync/soma */ function initrampgenCC(compartment) str compartment //connects pulsegenator to the compartment if (-1 == {getmsg {compartment} -find /rampgen INJECT}) echo "Creating message from /rampgen to" {compartment} addmsg /rampgen {compartment} INJECT output end end /* Function stepsCC initializes a pulsegen object and injects current into a compartment specified in initstepsCC (typically soma) in basic steps as specified by arguments. This function assumes that the model has been allowed to run for some reasonable amount of time to establish a reasonable baseline prior to calling this function, or that the baseline value and time is sufficient to reach steady/stable state. Takes the following arguments float baselevel : the holding iinj level in A float basetime : duration of baseline level in seconds float level : pulse 1 level float dlevel : change in pulse level with each pulse float width : pulse 1 width in seconds int npulses : number of pulses str compartment : compartment to inject current into (typically soma) e.g.: stepsCC 0 0.5 -1e-9 0.20e-9 0.5 10 /HE_sync_R/soma would execute 8 0.5 second pulses off of a baseline 0nA (held for 0.5 seconds) from -1.0 na to +1.0 na */ function stepsCC(baselevel, basetime, level, dlevel, width, npulses) float baselevel, basetime, level, dlevel, width int npulses int ipulse float totaltime = {basetime + width} echo "Setting up CC; arguments:" {baselevel}, {basetime}, {level}, {dlevel}, {width}, {npulses} //Initialize pulsegenerator setfield /pgen baselevel {baselevel} delay1 {basetime} width1 {width} trig_mode 0 for (ipulse = 0; ipulse <npulses; ipulse = ipulse + 1) echo setting level to {level + ipulse * dlevel} and stepping for {width}s // set pgen to appropriate value, then step for basetime + width setfield /pgen level1 {level + ipulse * dlevel} step {totaltime} -t end end /* Function rampCC creates a calculator object and injects current into the given compartment (typically soma) in basic ramp as specified by arguments. This function assumes that the model has been allowed to run for some reasonable amount of time to establish a baseline prior to calling this function, or that the baseline value and time is sufficient to reach steady state. Baseline is repeated at the end (_/\_/\_). Takes the following arguments float baselevel : the holding Vm level float basetime : duration of baseline level in seconds float peak : peak command voltage float width : duration of ramp width in seconds int nreps : number of repetitions of the ramp e.g.: rampCC -0.3 5 1 10 2 /HE_sync_R/soma would execute 2 10 second ramps off of a baseline -0.3 na (held for 5 seconds) up to +1.0 na (5s up, 5s down) */ function rampCC(baselevel, basetime, peak, width, nreps) float baselevel, basetime, peak, width int nreps int irep // TODO:check for erroneous input (e.g. width <=0) echo arguments: {baselevel}, {basetime}, {peak}, {width}, {nreps} float tstep = {getclock 0} float istep = {tstep*(peak - baselevel)/(width/2)} float totaltime = {basetime + width} float halfwidth = {width/2} echo " " tstep: {tstep} istep: {istep} totaltime: {totaltime} halfwidth: {halfwidth} //setclock 4 9999 // set the 'blank' reset to a very long time //sets up calculator element and connects it to the compartment setfield /rampgen/istep x {istep} // if messages have not been setup yet, do so if (-1 == {getmsg /rampgen -find /rampgen/istep SUM}) addmsg /rampgen/istep /rampgen SUM x end // moved to separate function to be compatible with Hines solver. for (irep = 0; irep <nreps; irep = irep + 1) //baseline for basetime setfield /rampgen output_init {baselevel} setfield /rampgen resetclock 0 step {basetime} -t // first half of ramp setfield /rampgen resetclock 4 setfield /rampgen/istep x {istep} step {halfwidth} -t // second half of ramp setfield /rampgen resetclock 4 setfield /rampgen/istep x {-istep} step {halfwidth} -t end //baseline for basetime setfield /rampgen output_init {baselevel} setfield /rampgen resetclock 0 step {basetime} -t setfield /rampgen output_init 0 setfield /rampgen resetclock 0 //setclock 0 {currentclock} end // ------------------------------------------------------ /* createVC(compartment) Creates and hooks up voltage clamp element to specified compartment element Also creates the base elements for the ramp and pulse protocols. */ function createVC(compartment) str compartment // TODO: add checks for existance of these objects before creation/hookup. // create vclamp objects values from Neurokit vclamp.g create diffamp /Vclamp setfield ^ saturation 999.0 gain 0.002 // (1/R) create RC /Vclamp/lpfilter setfield ^ R 500.0 C 1e-7 // tau = RC. Should result in 0.05 ms tau unless units are off create PID /Vclamp/PID setfield ^ gain 1e-6 tau_i 2e-5 tau_d 5e-6 saturation 999.0 // gain ~10/Rin of cell // create pulsegen and calculator for step and ramp protocols create pulsegen /pgen // for step protocols _--_ create calculator /rampgen // for ramp protocols _/\_ create neutral /rampgen/vstep // for ramp protocols _/\_ // hookup vclamp elements (but not source) addmsg /Vclamp/lpfilter /Vclamp PLUS state addmsg /Vclamp /Vclamp/PID CMD output addmsg {compartment} /Vclamp/PID SNS Vm addmsg /Vclamp/PID {compartment} INJECT output end /* Function stepsVC creates a pulsegen object connected to a preexisting voltage clamp object and clamps voltage in basic steps as specified by arguments. This function assumes that the model has been allowed to run for some reasonable amount of time to establish a reasonable baseline prior to calling this function, or that the baseline value and time is sufficient to reach steady state. Takes the following arguments float baselevel : the holding Vm level float basetime : duration of baseline level in seconds float level : pulse 1 level float dlevel : change in pulse level with each pulse float width : pulse 1 width in seconds int npulses : number of pulses e.g.: stepsVC -0.070 0.5 -0.060 0.010 0.5 8 would execute 8 0.5 second pulses off of a baseline -70 mV (held for 0.5 seconds) from -60 to +20 mV */ function stepsVC(baselevel, basetime, level, dlevel, width, npulses) float baselevel, basetime, level, dlevel, width int npulses int ipulse float totaltime = {basetime + width} //connects pulsegenator to the voltage clamp if (-1 == {getmsg /Vclamp/lpfilter -find /pgen INJECT}) addmsg /pgen /Vclamp/lpfilter INJECT output end //addmsg /pgen /Vclamp/lpfilter INJECT output echo arguments {baselevel}, {basetime}, {level}, {dlevel}, {width}, {npulses} float currentclock = {getclock 0} //save current clock and set to smaller time step to avoid numerical instability setclock 0 1.5258789062500000E-005 //1/(2^16) setfield /pgen baselevel {baselevel} delay1 {basetime} width1 {width} trig_mode 0 for (ipulse = 0; ipulse <npulses; ipulse = ipulse + 1) // set pgen to appropriate value, then step for basetime + width echo setting level to {level + ipulse * dlevel} and stepping for {totaltime}s setfield /pgen level1 {level + ipulse * dlevel} step {totaltime} -t end setclock 0 {currentclock} end /* Function rampVC creates a calculator object connected to a preexisting voltage clamp object and clamps voltage in basic ramp as specified by arguments. This function assumes that the model has been allowed to run for some reasonable amount of time to establish a reasonable baseline prior to calling this function, or that the baseline value and time is sufficient to reach steady state. Takes the following arguments float baselevel : the holding Vm level float basetime : duration of baseline level in seconds float peak : peak command voltage float width : duration of ramp width in seconds int nreps : number of repetitions of the ramp e.g.: rampVC -0.070 0.5 0 1 2 would execute 2 1 second ramps off of a baseline -70 mV (held for 0.5 seconds) up to 0 (.5s up, .5s down) */ function rampVC(baselevel, basetime, peak, width, nreps) float baselevel, basetime, peak, width int nreps int irep // TODO:check for erroneous input (e.g. width <=0) echo arguments {baselevel}, {basetime}, {peak}, {width}, {nreps} float currentclock = {getclock 0} //save current clock and set to smaller time step to avoid numerical instability setclock 0 {2**(-16)} //TODO: check need for changes to clock with Hines solver float tstep = {getclock 0} float vstep = {tstep*(peak - baselevel)/(width/2)} float totaltime = {basetime + width} float halfwidth = {width/2} echo " " tstep:{tstep} vstep:{vstep} totaltime:{totaltime} halfwidth:{halfwidth} setclock 4 9999 // set the 'blank' reset to a very long time //sets up calculator element and connects it to the voltage clamp setfield /rampgen/vstep x {vstep} addmsg /rampgen/vstep /rampgen SUM x addmsg /rampgen /Vclamp/lpfilter INJECT output //setfield /pgen baselevel {baselevel} delay1 {basetime} width1 {width} trig_mode 0 for (irep = 0; irep <nreps; irep = irep + 1) //baseline for basetime setfield /rampgen output_init {baselevel} setfield /rampgen resetclock 0 step {basetime} -t // first half of ramp setfield /rampgen resetclock 4 setfield /rampgen/vstep x {vstep} step {halfwidth} -t // second half of ramp setfield /rampgen resetclock 4 setfield /rampgen/vstep x {-vstep} step {halfwidth} -t end setclock 0 {currentclock} end /* Function BlockChannels loops over each channel (element) in each compartment and sets its Gbar to 0. Currently useing hardcoded base neutral objects for each cell of a single pair. Takes two arguments int verbose; if 1, echos all feedback about operation, if 2, echos changes only, if 0, echos nothing string blockedChannels - space delimited list of channel names to block e.g.: BlockChannels 1 "Na_ron P_ron" "8" "peri sync" note: leak conductance is not adjusted by this function Also this does not zero out synaptic conductance, although that would be affected by many of these manipulations. Synaptic conductance manipulation is handled elsewhere. */ function BlockChannels(verbose, blockedChannels, HE_ganglia, coord_modes) int verbose str blockedChannels, HE_ganglia, coord_modes str curHE, curMode, compartment, channel, blockedChannel, cell foreach curHE({arglist {HE_ganglia}}) foreach curMode({arglist {coord_modes}}) cell = {"/HE"@{curHE}@"_"@{curMode}@"/"} if(1==verbose) echo looping over compartments in {cell} end foreach compartment({el {cell}#}) if(1==verbose) echo " " looping over channels in compartment {compartment} end foreach channel({el {compartment}/#}) if(1==verbose) echo " " checking if {substring {channel} {{strlen {compartment}}+1}} is in list: {blockedChannels} end foreach blockedChannel({arglist {blockedChannels}}) if(0=={strcmp {substring {channel} {{strlen {compartment}}+1}} {blockedChannel}}) // could add tests to ensure this is a tabchannel (isa function), but skipping this test for now if(verbose >= 1) echo " --" setting {channel} Gbar to 0 end setfield {channel} Gbar 0 end end end end end end end // --------------------------- Bath/Drug Protocols --------------------------- // "blocks" K channels function TEAelectrodes(verbose, HE_ganglia, coord_modes) BlockChannels {verbose} "K1_ron K2_ron A_ron" {HE_ganglia} {coord_modes} end // "blocks" Ca channels, currently does not block chemical synaptic transmission (though perhaps it should..) function zeroCaPerfusion(verbose, HE_ganglia, coord_modes) BlockChannels {verbose} "CaS_ron" {HE_ganglia} {coord_modes} end // "blocks" K_Ca channels // currently does not block chemical synaptic transmission (though it should..) // this simulates calcium substitution. Should adjust Ca current by permeability of replaced ion. // could be considered equivalent to intracellular (electrode) fast chelators function CaSubPerfusion(verbose, HE_ganglia, coord_modes) BlockChannels {verbose} "K_Ca" {HE_ganglia} {coord_modes} end // "blocks" Na channels, currently does not block chemical synaptic transmission (though perhaps it should..) function zeroNaPerfusion(verbose, HE_ganglia, coord_modes) BlockChannels {verbose} "Na_ron P_ron" {HE_ganglia} {coord_modes} end // "blocks" all channels function BlockAllChannels(verbose, HE_ganglia, coord_modes) BlockChannels {verbose} "K1_ron K2_ron A_ron CaS_ron K_Ca Na_ron P_ron" {HE_ganglia} {coord_modes} end // ---------------------------- E-Phys Protocols ------------------------------ // blocks synaptic input, executes a 5s baseline, 10s ramp protocol from -0.4 nA to +1.0 nA function ficurve(verbose) // block inhibitory input set_synE_only {coordmodes} {HNganglia} {HEganglia} // this function is in SynapticInput.g //rampCC(baselevel, basetime, peak, width, nreps) rampCC -0.3e-9 5 1e-9 10 4 //HE_sync_R/soma CaSubPerfusion {verbose} rampCC -0.3e-9 5 1e-9 10 4 //HE_sync_R/soma end // blocks synaptic input, executes a 10s baseline (0nA), 10s or 30s ramp protocol from 0 nA to -0.5 nA function fiInhibitionCurve(verbose) // block inhibitory input set_synE_only {coordmodes} {HNganglia} {HEganglia} // this function is in SynapticInput.g rampCC 0 10 -5e-10 5 2 rampCC 0 10 -5e-10 10 2 rampCC 0 10 -5e-10 30 2 end // measure K_Ca from soma with voltage clamp function measureKCa(verbose) zeroNaPerfusion {verbose} // block inhibitory input set_synE_only {coordmodes} {HNganglia} {HEganglia} // this function is in SynapticInput.g // createVC called prior to this call.. //check stepsVC -0.070 4 -0.060 0.010 4 8 zeroCaPerfusion {verbose} //CaSubPerfusion {verbose} // or stepsVC -0.070 4 -0.060 0.010 4 8 stepsVC -0.070 4 -0.000 0.000 0 1 end // measure K_Ca from soma with voltage clamp, blocking other K current function measureKCasolo(verbose) zeroNaPerfusion {verbose} TEAelectrodes {verbose} // block inhibitory input set_synE_only {coordmodes} {HNganglia} {HEganglia} // this function is in SynapticInput.g // createVC called prior to this call.. //check stepsVC -0.070 4 -0.060 0.010 4 8 zeroCaPerfusion {verbose} //CaSubPerfusion {verbose} // or //check stepsVC -0.070 4 -0.060 0.010 4 8 stepsVC -0.070 4 -0.000 0.000 0 1 end // current clamp protocol to measure synaptic reversal function synapticReversal(verbose) zeroNaPerfusion {verbose} //set_synE_zero check reset stepsCC 0 0 -.35e-9 0.02e-9 6 11 /HE_sync_R/soma end // current clamps to measure coupling, input R function measureCoupling(verbose) zeroNaPerfusion {verbose} set_synE_only {coordmodes} {HNganglia} {HEganglia} // this function is in SynapticInput.g check reset stepsCC 0 2 -1e-9 0.5e-9 2 3 /HE_sync_R/soma end