/*Investigation of the role of Apical and Basal dendrites on L2/3 V1 Pyramidal Neuron Orientation Selectivity*/
/*Original model authored by Papoutsi A., September 2015*/
/*Modified by Petousakis K-E., 2019*/
load_file("nrngui.hoc")
objref tgt_times // Holds intervention timing information (t_pre and t_post for target somatic spikes)
objref tgts // Stores target dendritic tree (apical or basal)
objref weight_vec // Stores original conductances of mechanisms being intervened upon (so that the original conductances can be restored)
objref sf, tid // OBSOLETE (string manipulation helper objects)
strdef mstr, c // -//-
objref currclamp, tgt_segment // Objects relating to current clamp insertion (used for model validation/testing), alongside the variables cct and cca
// Print parameters
bnf2=(bnf+80)*0.01 //bnf=[0:1:40] -> bnf=[0.80:0.01:1.20] //Basal Na factor, transformed
anf2=(anf+80)*0.01 //anf=[0:1:40] -> anf=[0.80:0.01:1.20] //Apical Na factor, transformed
//---------Parameter list-----------//
// The values of these parameters are provided externally via .sh files that contain specific parameter combinations, corresponding to different experimental setups.
// Not all parameters listed here are actively in use in this particular file. Some are used by other files, such as the one responsible
// for synaptic orientation preference allocation and synapse initialization and distribution (stimulus_uniform_basalvar.hoc).
// Certain parameters are mathematically transformed after being input from the .sh file of the experiment. This is generally done to avoid decimal points in the .sh files. An example can be
// seen above, in the "bnf2"/"anf2" variables, which hold the transformed vaues of the "bnf"/"anf" input parameters. Thus, values in the [0,40] range are transformed into values in the
// [0.8, 1.2] range (in this case).
// Parameters may be quantitative (i.e. quantities or percentages that change the model in some way), or control variables that change the logic of the experiment (e.g. which
// dendritic tree is the target of an intervention experiment).
//basal_width: intended tuning width of the basal tree (distribution standard deviation; always set to the default of 30 deg.)
//apical_width: intended tuning width of the apical tree (distribution standard deviation; always set to the default of 30 deg.)
//stimulus_presentation: orientation of the presented stimulus (in deg)
//tag_basal: mean preferred orientation of the entire basal tree (variable)
//tag_apical: mean preferred orientation of the entire apical tree (always set to 0)
//disp: controls width of synaptic orientation preference distribution (always set to 0)
//n_neuron: neuron ID - allows for different variations in starting synaptic preference distribution
//n_run: simulation ID - allows for different variations in input spike trains
//abltd: controls whether the apical tree has been removed (ablated) (default value is 0)
//dend_id1, dend_id2 : ids of basal dendrites that are to be cut (cut_basal condition). Ids are 0-4. If they are the same, then only 1 is cut (or none, if cut_basal=0)
// These parameters are not used (cut_basal is always set to 0), they are part of the original model.
//apw, bw : apical/basal dendrite tuning widths
//stim: orientation of presented stimulus
//run, neuron : run and neuron number. Start at 0.
//istim: Controls the mean frequency of excitatory stim-driven input.
//swf: Synaptic (excitatory) Weight Factor. Modifies AMPA/NMDA weights.
//iwf: Inhibition Weight Factor. Modifies GABAa weight.
//inhdist: Distribution of (background) Inhibition. Changes apical/basal (background) inhibition ratio.
//excdist: Distribution of (background) Excitation. Changes apical/basal (background) excitation ratio.
//excdist_stim: Distribution of (stim-driven) Excitation. Changes apical/basal (stim-driven) excitation ratio.
//scf: Synapse Count Factor. Rescales synaptic density.
//bnf2,anf2: basal/apical Na factor, transformed from original values (bnf,anf) - "default" value for bnf/anf = 20
// Rescales sodium conductance for the basal/apical trees to +/- 20% of the baseline value.
//sttx, bttx, attx: Somatic/Basal/Apical TTX (g_na = 0) application (1 for yes, 0 for no)
//nsB, nsA: no Stimulation Basal/Apical (1 to remove stim-driven input, 0 to keep it)
//niB, niA: no Inhibition Basal/Apical (1 to remove inhibition, 0 to keep it)
//nbB, nbA: no background Basal/Apical (1 to remove background excitation, 0 to keep it)
//valcrit: (dendritic) Validation Criterion. -1 to disable. 0-49 corresponds to each dendrite in sequence. 50 is for all dendrites.
//scalefactor: synaptic count rescaling variable - if 1, synapses increase by 1 per step. If 2, they increase by 2 per step etc.
//dtext: external simulation time step (/1000 to get real value in ms)
//dtstopext: external simulation total runtime (in ms)
//cct: Current Clamp Timing (for testing/validation)
//cca: Current Clamp Amplitude (for testing/validation)
//runtype: Enables (1) or disables (0) sodium conductance intervention experiment logic.
//identifier: Indirectly switches intervention experiment logic to target apical (-1) or basal (1) dendrites.
//dend_record: Toggles saving voltage traces from individual dendritic compartments/branches on (1) or off (0).
//t_pre/t_post: Intervention timing (pre-spike and post-spike) for single-spike interventions.
//curr_record: Toggles saving current traces (default is 0)
//val_bas: Unused - no effect (default value: -1).
//val_ap: Unused - no effect (default value: -1).
//tag_rec: toggle to allow recording synaptic orientation preferences.
//val_na: toggle for the validation of sodium activity - disables NMDA receptor activity by setting their conductance to 0.
//ibg: Controls the mean frequency of background excitatory input.
//iinh: Controls the mean frequency of background inhibitory input.
//stimintv: Similar to runtype, it enables or disables (1/0) synaptic intervention experiment logic.
//validation_clustered: Switches synaptic distribution from uniform across the section to section center (x=0.5) clustering if set to 1 (default: 0)
//ampaA_stim_fct: Percentage of apical stim-driven AMPA receptor weight that remains during synaptic intervention experiments.
//ampaB_stim_fct: Percentage of basal stim-driven AMPA receptor weight that remains during synaptic intervention experiments.
//nmdaA_stim_fct: Percentage of apical stim-driven NMDA receptor weight that remains during synaptic intervention experiments.
//nmdaB_stim_fct: Percentage of basal stim-driven NMDA receptor weight that remains during synaptic intervention experiments.
//Astim_ampaf: Scaling factor for apical stimulus-driven AMPA synapse weights (applied at simulation initialization and lasts throughout the simulation)
//Astim_nmdaf: Scaling factor for apical stimulus-driven NMDA synapse weights (applied at simulation initialization and lasts throughout the simulation)
//Bstim_ampaf: Scaling factor for basal stimulus-driven AMPA synapse weights (applied at simulation initialization and lasts throughout the simulation)
//Bstim_nmdaf: Scaling factor for basal stimulus-driven NMDA synapse weights (applied at simulation initialization and lasts throughout the simulation)
//delFB_stim_exc: Delay (in ms) applied to excitatory feedback (apical stimulus-driven) synapses (default value: 10 ms)
//delFB_stim_bg: Delay (in ms) applied to apical background-driven (noise) synapses (default value: 0 ms)
//delFB_stim_inh: Delay (in ms) applied to apical inhibitory synapses (default value: 0 ms)
print "dend_id1=", dend_id1, " dend_id2=", dend_id2, " tagB=", tag_basal, " apw=", apical_width, " bw=", basal_width, " stim=", stimulus_presentation, " run=", n_run, "neuron=", n_neuron, "istim=",(istim/10000), "swf=", swf, "inhdist=", inhdist, "excdist=", excdist, "excdist_stim=", excdist_stim, "scf=", ((50+(scf*5))/100), "bnf2=", bnf2, "anf2=", anf2, "sttx=",sttx, "bttx=",bttx,"attx=",attx,"nsB=",nsB,"nsA=",nsA,"niB=",niB,"niA=",niA,"nbB=",nbB,"nbA=",nbA,"valcrit=",valcrit,"scalefactor=",scalefactor,"dt=",(dtext/1000), "runtype=", runtype
strdef temp_dir, temp_mkdir, tstr, temp_save
// Toggles dendritic ablation
if (abltd==2) {
ablated=0
cut_basal=1
print "cut_basal case"
} else{
ablated=abltd
cut_basal=0
print "control/ablated case"
}
// Open libraries / cell setup
xopen("basic-graphics.hoc")
xopen("morphologies/neuron1_modified.hoc")
xopen("./cell_setup.hoc")
xopen("delete_primary_basal.hoc")
xopen("./exp_protocols.hoc")
//Set parameters
tstop = dtstopext
dt=(dtext/1000) // in ms
steps_per_ms=1/dt
//Special control variables for troubleshooting/parameter space exploration
flagBG=0 //special use flag used to nullify BackGround synapses (excitatory + inhibitory) (deprecated/testing)
flagSD=0 //special use flag used to nullify Stim-Driven synapses (deprecated/testing)
//Synaptic weights
swf=4500+(swf*100)
print "AMPA/NMDA weight factor (/10000):", swf
if (ablated) {
ampa_g=0.00084*(swf/10000)
nmda_g=0.00115*(swf/10000)
gaba_g=0.00125*(iwf/10000)
} else{
ampa_g=0.00084*(swf/10000)
nmda_g=0.00115*(swf/10000)
gaba_g=0.00125*(iwf/10000)
}
if (val_na) {
nmda_g = 0
print "Dendritic Na+ spike validation - NMDA weight set to 0"
}
addgraph_2("soma.v(0.5)", 0,tstop, -75, 50)
//-----------------Background synapses
tl=3298.1508 //Total Length of Neuron
syn_exc_total=round(tl* ((50+(scf*5))/100) ) //Assume synaptic density 2/micrometer
syn_exc=round(75*syn_exc_total/100) //25% of spines are visual responsive, Chen et al. 2013, rest set as background input.
syn_basal=round((excdist/1000)*syn_exc) //deFelipe, Farinas,1998
syn_apical=round(((1000-excdist)/1000)*syn_exc) //deFelipe, Farinas,1998
print "(Background) Basal excitatory=",syn_basal, "Apical excitatory=",syn_apical
syn_inh=round(syn_exc_total*15/85) //15% Binzegger,Martin, 2004 (L2/3, cat V1)
syn_inh_soma=round(syn_inh*7/100) //deFelipe, Farinas,1998
syn_inh_apical=round(syn_inh*(inhdist/1000))
syn_inh_basal=round(syn_inh*((930-inhdist)/1000))
print "(Background) Basal Inhibitory=",syn_inh_basal, "Apical Inhibitory=",syn_inh_apical, "Somatic Inhibitory=",syn_inh_soma
Hz= (ibg/10000) //Mean frequency of background excitatory synapse activation - 1.5 events/min (Takahashi 2012, Lohman, 2015) Lohman says 0.6/min=> 0.01Hz
Hz_inh= (iinh/10000) //Mean frequency of (background) inhibitory synapse activation - Adjust so that the overall spontaneous spiking frequency is ~0.16Hz - Crochet, Petersen 2011.
//------------------Stimulus Properties
tag_apical=0
disparity=tag_basal-tag_apical
s_Hz=(istim/10000) // Mean frequency of stim-driven excitatory synapse activation
stimulus_duration=2000 // Stimulus lasts 2s
total_syn=round(25*syn_exc_total/100) //25% of spines are visual responsive, Chen et al. 2013
total_syn_apic=round(total_syn*((1000-excdist_stim)/1000))
total_syn_basal=round(total_syn*(excdist_stim/1000))
print "(Stimulus) Basal excitatory=",total_syn_basal, "Apical excitatory=",total_syn_apic
//--Set parameters
find_prim_dendrites ()
num_seed=basal_width*apical_width*(tag_basal+1)*10000*(n_run+1)*(n_neuron+1)
num_seed2=basal_width*apical_width*(tag_basal+1)*10000*(n_neuron+1)
//Load Background-Stimulus Protocols
xopen("background_uniform.hoc")
xopen("stimulus_uniform_basalvar.hoc")
// Make directory to save data
strdef temp_dir, temp_mkdir, temp_save, tstr
if (ablated) {
sprint(temp_dir,"./results/stim_%d/neuron_%d/run_%d",stimulus_presentation,n_neuron,n_run)
}
if (cut_basal) {
if (dend_id2==dend_id1) {
sprint(temp_dir,"./results/stim_%d/neuron_%d/run_%d",stimulus_presentation,n_neuron,n_run)
} else {
sprint(temp_dir,"./results/stim_%d/neuron_%d/run_%d",stimulus_presentation,n_neuron,n_run)
}
}
if (!(ablated+cut_basal)){
sprint(temp_dir,"./results/stim_%d/neuron_%d/run_%d",stimulus_presentation,n_neuron,n_run)
}
if (unix_mac_pc()==3){ // checks whether OS is windows-based
//These commands are for windows-based systems only
sprint(temp_mkdir, "mkdir -p %s", temp_dir)
WinExec(temp_mkdir)
} else{
//These commands are for linux-based systems only
sprint(temp_mkdir, "mkdir -p %s", temp_dir)
system(temp_mkdir)
}
xopen("record_save_data.hoc")
xopen("getpaths.hoc")
//--------------------Run the simulation ------------------------
ttx(sttx,bttx,attx) //"Application of TTX" (compartment g_na=0) for soma (sttx), basal dendrites (bttx) and apical dendrites (attx)
nullinh(niS,niB,niA) // nullifiy inhibition Somatic (niS), nullify inhibition Basal (niB), nullify inhibition Apical (niA) - removes the corresponding synapses
nullstim(nsB,nsA) // nullifiy stimulus Basal (nsB), nullify stimulus Apical (nsA) - removes the corresponding synapses
nullbg(nbB,nbA) // nullify background Basal (nbB), nullify background Apical (nbA) - removes the corresponding synapses (excitatory only - inhibitory removed by niB, niA)
if (cct != -1){
print "Current clamp applied on compartment ", cct, " with a current of ", cca, " pA"
if (cct < 7){
tgt_segment = basal.o(cct)
}
if (cct >= 7){
tgt_segment = apical.o(cct-7)
}
tgt_segment currclamp = new IClamp(0.5)
currclamp.del = 500
currclamp.dur = 200
currclamp.amp = cca
}
background_activity ()
stimulus()
// Execution of ablation-specific procedures
if (ablated) {
delete_apical()
}
if (cut_basal) {
delete_primary_dendrites(dend_id1, dend_id2)
}
// Voltage recordings from soma and dendrites
rec_soma()
if (dend_record==1){
rec_dend()
}
// Sodium conductance interventions logic
if(runtype != 0) { // mixed nullification (apical and basal)
tgt_times = new Vector()
tgts = new Vector()
tgt_times.append(tpre) //timing, float
tgt_times.append(tpost) //timing, float
if (identifier > 0){
tgts.append(1)
}else{
tgts.append(0)
}
iter_counter = 0
nspikes = abs(runtype) // runtype is 1 for single spike nullification
for reps = 0, nspikes-1 {
if (reps == 0) {finitialize()} // finitialize during first iteration to start
// Start of targets.txt parser
tid = new Vector()
flag = tgts.x(0)
if (flag==1) {
print "Found basal nullification @ ", tgt_times.x(iter_counter), " ms."
for j = 0, 6 {
tid.append(j) //flag all basals for nullification
}
}else { // flag == 0
print "Found apical nullification @ ", tgt_times.x(iter_counter), " ms."
for j = 0, 42 {
tid.append(j) //flag all apicals for nullification
}
}
continuerun(tgt_times.x(iter_counter)) //continuerun until the Nth time in vector
print "Reached time before target spike @ ", tgt_times.x(iter_counter), " ms."
weight_vec = new Vector()
if (flag == 1){
for i = 0, 6 {
if(tid.x(i) != -1){
access basal.o(i).sec
weight_vec.append(gbar_na)
gbar_na = 0
print "Basal dendrite ", i," sodium conductance temporarily nullified."
}
}
}
if (flag == 0){
for i = 0, 42 {
if(tid.x(i) != -1){
access apical.o(i).sec
weight_vec.append(gbar_na)
gbar_na = 0
print "Apical dendrite ", i," sodium conductance temporarily nullified."
}
}
}
continuerun(tgt_times.x(iter_counter+1))
print "Reached time after target spike @ ", tgt_times.x(iter_counter+1), " ms."
counter = 0
if (flag == 1){
for i = 0, 6 {
if(tid.x(i) != -1){
access basal.o(i).sec
gbar_na = weight_vec.x(counter)
print "Basal dendrite ", i," sodium conductance restored."
counter += 1
}
}
}
if (flag == 0){
for i = 0, 42 {
if(tid.x(i) != -1){
access apical.o(i).sec
gbar_na = weight_vec.x(counter)
print "Apical dendrite ", i," sodium conductance restored."
counter += 1
}
}
}
iter_counter +=2 //move to next spiking event (because timings are pairs, not single numbers)
}
continuerun(tstop)
}
// Stim-driven synapse interventions logic
if(stimintv != 0) { // mixed nullification (apical and basal)
tgt_times = new Vector()
tgts = new Vector()
tgt_times.append(tpre) //timing, decimal
tgt_times.append(tpost) //timing, decimal
if (identifier > 0){
tgts.append(1)
}else{
tgts.append(0)
}
iter_counter = 0
nspikes = abs(stimintv) // runtype is 1 for single spike nullification
for reps = 0, nspikes-1 {
if (reps == 0) {finitialize()} // finitialize during first iteration to start
// Start of targets.txt parser
tid = new Vector()
flag = tgts.x(0)
if (flag==1) {
print "Found basal stim synapse nullification @ ", tgt_times.x(iter_counter), " ms."
for j = 0, 6 {
tid.append(j) //flag all basals for nullification
}
}else { // flag == 0
print "Found apical stim synapse nullification @ ", tgt_times.x(iter_counter), " ms."
for j = 0, 42 {
tid.append(j) //flag all apicals for nullification
}
}
continuerun(tgt_times.x(iter_counter)) //continuerun until the Nth time in vector
print "Reached time before target spike @ ", tgt_times.x(iter_counter), " ms."
weight_vec = new Vector()
if (flag == 1){
syn=0
for i = 0, 6 {
for j=0, mat_bas_st.x(i)-1 {
nc_stim_basal_ampa[syn].weight=ampa_g*(ampaB_stim_fct/100)
nc_stim_basal_nmda[syn].weight=nmda_g*(nmdaB_stim_fct/100)
syn=syn+1
}
}
print "Basal AMPA and NMDA stim-driven synapse weights set to ", ampaB_stim_fct, "% and ", nmdaB_stim_fct, "% weight, respectively."
}
if (flag == 0){
syn=0
for i = 0, 42 {
for j=0, mat_ap_st.x(i)-1 {
nc_stim_apical_ampa[syn].weight=ampa_g*(ampaA_stim_fct/100)
nc_stim_apical_nmda[syn].weight=nmda_g*(nmdaA_stim_fct/100)
syn=syn+1
}
}
print "Apical AMPA and NMDA stim-driven synapse weights set to ", ampaA_stim_fct, "% and ", nmdaA_stim_fct, "% weight, respectively."
}
continuerun(tgt_times.x(iter_counter+1))
print "Reached time after target spike @ ", tgt_times.x(iter_counter+1), " ms."
counter = 0
if (flag == 1){
syn=0
for i = 0, 6 {
for j=0, mat_bas_st.x(i)-1 {
nc_stim_basal_ampa[syn].weight=ampa_g*1
nc_stim_basal_nmda[syn].weight=nmda_g*1
syn=syn+1
}
}
print "Basal AMPA and NMDA stim-driven synapse weights restored to 100%."
}
if (flag == 0){
syn=0
for i = 0, 42 {
for j=0, mat_ap_st.x(i)-1 {
nc_stim_apical_ampa[syn].weight=ampa_g*1
nc_stim_apical_nmda[syn].weight=nmda_g*1
syn=syn+1
}
}
print "Apical AMPA and NMDA stim-driven synapse weights restored to 100%."
}
iter_counter +=2 //move to next spiking event (because timings are pairs, not single numbers)
}
continuerun(tstop)
}
if(runtype==0) {
run()
}
if(tag_rec){
save_tags2()
}
save_soma()
if (dend_record==1){
save_dend()
}
//That's the end!