// put excitatory, inhibitory synapses everywhere so they can be used if desired
// 20121124 This new version has added Exp2SynCur where ever inhib
// synapses were previously placed.  That way if desired the current based
// (the driving force is fixed) inhibitory synapse can be used instead.
objref excitatory[1000], inhibitory[1000], inhib_exp2syn[1000], inhib_exp2syncur[1000]
// store references for up to 1000 excitatory, inhibitory
// and inhibitory Exp2Syn synapses
objref esyn_list, isyn_list, i_exp2syn_list, i_exp2syncur_list
objref spine_head_inhib, spine_head_excite, adj_dend_inhib, adj_dend_excite
esyn_list = new List() // stores trapezoidal excit syns
isyn_list = new List() // stores trapezoidal inhib syns
i_exp2syn_list = new List()
i_exp2syncur_list = new List()
isyn=0 // indicies for about to be newly created synaptic point processes
esyn=0 // these excitatory and inhibitory synapses are trapezoidal
i_exp2syn = 0  // indicies for Exp2Syn type inhibitory synapses
i_exp2syncur = 0  // indicies for Exp2SynCur type inhibitory synapses
print "excitatory synapses"
dendrite  {
    {
    location=adjacent_shaft_x_loc // initially 181/L
    excitatory[esyn] = new ZoidSyn(location)
      print "position x=",adjacent_shaft_x_loc,", ", secname(),", excitatory[", esyn,"] located at approx. ",L*location, " microns."
    }
    just_a_couple += 1
    esyn_list.append(excitatory[esyn])
    // the default reversal potential is 0 mV so .e doesn't needs to be changed
    excitatory[esyn].trf = 1
    excitatory[esyn].interval = 3
    esyn=esyn+1
  }

print esyn_list.count," created"
just_a_couple = 0
for i=0, esyn_list.count()-1 {
 esyn_list.o(i).g=0 // start out with no excitatory conductance however then below
}
print "\ninhibitory synapses!"
// *** trapezoidal synapses ***
dendrite  {
    location = adjacent_shaft_x_loc // initially 181/L
    inhibitory[isyn] = new ZoidSyn(location)    //new ZoidSyn(191/L)
      print "position x=",adjacent_shaft_x_loc,", ", secname(),", inhibitory[", isyn,"] located at approx. ",L*location, " microns."
    isyn_list.append(inhibitory[isyn])
    inhibitory[isyn].e=-70 // our default for an inhibitory synapse
    inhibitory[isyn].trf = 1
    inhibitory[isyn].interval = 3
    isyn=isyn+1
}
forsec "head"  {
  for (x,0) {
    location=x
    inhibitory[isyn] = new ZoidSyn(location)    
      print "position x=",x,", ", secname(),", inhibitory[", isyn,"] located at approx. ",L*location, " microns."
    isyn_list.append(inhibitory[isyn])
    if (!strcmp(secname(),"Spine[2].head")) {
      spine_head_inhib = inhibitory[isyn]
      print "specially created variables:"
      print "spine_head_inhib=inhibitory[",isyn,"]"
    }
    inhibitory[isyn].e=-70 // our default for an inhibitory synapse
    inhibitory[isyn].trf = 1
    inhibitory[isyn].interval = 3
    isyn=isyn+1
  }
}

// *** Exp2Syn *** synapses based on a global ipsc recorded by Chiu

// First setup a NetStim to stimulate any number of Exp2Syn's

objref ns
// ns is NetStim
ns=new NetStim(0.5) // what is the 0.5 specifying?
// and has to be connected: s = new NetStim(x)
/* with s to ns, below copied from QuickNRN:
ns.interval ms (mean) time between spikes
ns.number (average) number of spikes
ns.start ms (most likely) start time of first spike
ns.noise ---- range 0 to 1. Fractional randomness.
0 deterministic, 1 intervals have negexp distribution.d to any cell with a NetCon
*/
ns.start=100
ns.interval=15
ns.number=1

// the same netstim can stimulate any number of synapses (fan out)
// (one NetStim to target many synapses)

// NC: reserve a 1000 NetCon's (which connect the NetStim to the Exp2Syn's)
// NCcuranother 1000 for NetStim to Exp2SynCur's
objref NC[1000], NCcur[1000]
// let isyn match between the NetCon and Exp2Syn.  This means that some
// array elements NC[i] will not be used.
objref spine_head_exp2syn_inhib // extra handle to exp2syn
objref spine_head_exp2syncur_inhib // extra handle to exp2syncur
dendrite  {
    location=adjacent_shaft_x_loc // initially 181/L
    // Creating the Exp2Syn synapse and assigning it's default parameters
    inhib_exp2syn[i_exp2syn] = new Exp2Syn(location)    
      print "Exp2Syn position x=",adjacent_shaft_x_loc,", ", secname(),", inhib_exp2syn[", i_exp2syn,"] located at approx. ",L*location, " microns."
    i_exp2syn_list.append(inhib_exp2syn[i_exp2syn])
    NC[i_exp2syn] = new NetCon(ns,     inhib_exp2syn[i_exp2syn], 0.5  ,     1    , 0) // 0 weight in uS
    // docum. netcon = new NetCon(source, target,              threshold, delay, weight)
    inhib_exp2syn[i_exp2syn].e = -70
    // result of optimization 20120506
    inhib_exp2syn[i_exp2syn].tau1 = 5.1075381 
    inhib_exp2syn[i_exp2syn].tau2 = 73.879924 
    i_exp2syn=i_exp2syn+1
    // Creating the Exp2SynCur synapse and assigning it's default parameters
    inhib_exp2syncur[i_exp2syncur] = new Exp2SynCur(location)    
      print "Exp2SynCur position x=",adjacent_shaft_x_loc,", ", secname(),", inhib_exp2syncur[", i_exp2syncur,"] located at approx. ",L*location, " microns."
    i_exp2syncur_list.append(inhib_exp2syncur[i_exp2syncur])
    NCcur[i_exp2syncur] = new NetCon(ns,     inhib_exp2syncur[i_exp2syncur], 0.5  ,     1    , 0) // 0 weight in uS
    // docum. netcon = new NetCon(source, target,              threshold, delay, weight)
    inhib_exp2syncur[i_exp2syncur].e = -70
    // result of optimization 20120506
    inhib_exp2syncur[i_exp2syncur].tau1 = 5.1075381 
    inhib_exp2syncur[i_exp2syncur].tau2 = 73.879924 
    i_exp2syncur=i_exp2syncur+1
}
forsec "head"  {
  for (x,0) {
    location=x
    // setup the Exp2Syn synapses
    inhib_exp2syn[i_exp2syn] = new Exp2Syn(location)    
      print "Exp2Syn position x=",x,", ", secname(),", inhib_exp2syn[", i_exp2syn,"] located at ",L*location, " microns."
    i_exp2syn_list.append(inhib_exp2syn[i_exp2syn])
    if (!strcmp(secname(),"Spine[2].head")) {
      spine_head_exp2syn_inhib = inhib_exp2syn[i_exp2syn]
      print "specially created variables:"
      print "spine_head_exp2syn_inhib=inhib_exp2syn[",i_exp2syn,"]"
    }
    NC[i_exp2syn] = new NetCon(ns,     inhib_exp2syn[i_exp2syn], 0.5  ,     1    , 0) // 0 weight in uS
    // docum. netcon = new NetCon(source, target,              threshold, delay, weight)
    inhib_exp2syn[i_exp2syn].e = -70
    // result of optimization 20120506
    inhib_exp2syn[i_exp2syn].tau1 = 5.1075381 
    inhib_exp2syn[i_exp2syn].tau2 = 73.879924 
    i_exp2syn=i_exp2syn+1
    // setup the Exp2SynCur synapses
    inhib_exp2syncur[i_exp2syncur] = new Exp2SynCur(location)    
      print "Exp2SynCur position x=",x,", ", secname(),", inhib_exp2syncur[", i_exp2syncur,"] located at ",L*location, " microns."
    i_exp2syncur_list.append(inhib_exp2syncur[i_exp2syncur])
    if (!strcmp(secname(),"Spine[2].head")) {
      spine_head_exp2syncur_inhib = inhib_exp2syncur[i_exp2syncur]
      print "specially created variables:"
      print "spine_head_exp2syncur_inhib=inhib_exp2syncur[",i_exp2syncur,"]"
    }
    NCcur[i_exp2syncur] = new NetCon(ns,     inhib_exp2syncur[i_exp2syncur], 0.5  ,     1    , 0) // 0 weight in uS
    // docum. netcon = new NetCon(source, target,              threshold, delay, weight)
    inhib_exp2syncur[i_exp2syncur].e = -70
    // result of optimization 20120506
    inhib_exp2syncur[i_exp2syncur].tau1 = 5.1075381 
    inhib_exp2syncur[i_exp2syncur].tau2 = 73.879924 
    i_exp2syncur=i_exp2syncur+1
  }
}

print isyn_list.count," trapezoidal created"
print i_exp2syn_list.count, " exp2syn created"
print i_exp2syncur_list.count, " exp2syncur created"
for i=0, isyn_list.count()-1 {
 isyn_list.o(i).g=0 // start out with no inhibitory conductance however then below
}
// note that the NetCon weights were already set to zero. These can be set with NC[i_exp2syn].weight
x_value=0
proc print_um_of_seg() { // receives a 1<=segment<=nseg value, prints um
  segment = $1
  x_value = 0.5*(1/dendrite.nseg) + (segment-1)/dendrite.nseg
  print "Segment number ",segment," is located at x value ",x_value,", ",x_value*dendrite.L," microns along the dendrite of length ",dendrite.L  
  print "It runs from ",dendrite.L*(x_value-.5/nseg)," to ", dendrite.L*(x_value+.5/nseg)," microns."
}
micron=0
segnum=0
proc print_seg_of_um() { // receives a micron position on dend, prints nseg
  micron=$1
  // micron=x*L= (1/2*1/nseg+(n-1)/nseg)*L
  // micron/L = .5/nseg + (n-1)/nseg
  // micron*nseg/L = .5 + n-1
  // micron*nseg/L + .5 = n
  segnum=micron*dendrite.nseg/dendrite.L+.5
  print "A length ",micron," along the dendrite is segment number ", segnum," rounded to ",int(segnum+.5-1e-9)
  //  1e-9 serves as an epsilon that heuristically takes care of boundary cond.
}
isyn_=3
xpanel("Exp2Syn Synaptic Stimulation Control")
  xlabel("NetStim NetCon")
  xvalue("ns.interval")
  xvalue("ns.number")
  xvalue("ns.start")
  xvalue("ns.noise")
  xlabel("above are NetStim, below is NetCon values")
  xlabel("turn synapse OFF or ON by setting below NetCon to 0.0004 uS")
  xlabel("AND setting above ns.number to non-zero value")
  xvalue("NC[isyn_].weight")
  xvalue("isyn_")
  xlabel("Exp2Syn GABA_A (for isyn_ value=compartment:")
  xlabel("0=dendrite, 1=Spine[0], 2=Spine[1], 3=Spine[2]")
  xlabel("dendrite compartment initialized to near Spine[1])")
  xvalue("inhib_exp2syn[isyn_].tau1")
  xvalue("inhib_exp2syn[isyn_].tau2")
  xvalue("inhib_exp2syn[isyn_].e")
xpanel()
isyncur_=3
xpanel("Exp2SynCur Synaptic Stimulation Control")
  xlabel("NetStim NetCon")
  xvalue("ns.interval")
  xvalue("ns.number")
  xvalue("ns.start")
  xvalue("ns.noise")
  xlabel("above are duplicated NetStim, below is NetCon values")
  xlabel("turn synapse OFF or ON by setting below NetCon to 0.0004 uS")
  xlabel("AND setting above ns.number to non-zero value")
  xvalue("NCcur[isyncur_].weight")
  xvalue("isyncur_")
  xlabel("Exp2SynCur GABA_A (for isyncur_ value=compartment:")
  xlabel("0=dendrite, 1=Spine[0], 2=Spine[1], 3=Spine[2]")
  xlabel("dendrite compartment initialized to near Spine[1])")
  xvalue("inhib_exp2syncur[isyncur_].tau1")
  xvalue("inhib_exp2syncur[isyncur_].tau2")
  xvalue("inhib_exp2syncur[isyncur_].e")
xpanel()