begintemplate olmcell
public init, connect_sections, size_sections, append_sections
public mechinit, insert_mechs, set_biophys, get_root
public  pre_list, connect_pre, is_art, is_connected, gid, randi
public soma, dend
public all, basal_list, apical_list, soma_list, axon_list, dendrite_list
public x, y, z, position, myroot, Vrest
public NumSoma, NumApical, NumBasal, NumAxon

// strings
strdef myroot

// objects
objref syn, pre_list, templist, rootlist, this

// external variables
external numCellTypes, cellType

NumSoma=1
NumApical=0
NumBasal=2
NumAxon=1

create soma[NumSoma], dend[NumBasal], axon[NumAxon]


proc init() {
	gid = $1
	randi = $2
	
	// morphology
	connect_sections()	// local fcn: connect soma, dendrites, axon initial segment
	size_sections()		// local fcn: set the size dimensions of each section
	define_shape()		// builtin fcn: fill in 3d info for sections defined by only L and diam, translate 3d points for consistency with their connections 
  	append_sections()	// local fcn: append all sections to the section list
	set_nseg()			// local fcn: set the number of segments in each section
	get_root()			// local fcn: perform morphology checks

	// electrophysiology
	mechinit()			// local fcn: set values for max conductances and reversal potentials of ion channels and other ephys parameters that are subject to fitting
	insert_mechs()		// local fcn: insert ion channels and actually set values determined in the mechinit fcn
	set_chanparams()	// local fcn: after all channels have been inserted, then their other parameters can be set	
	// synapses
	pre_list = new List() // define a list for the presynaptic connections
	define_synapses($3)	// local fcn: define all possible synaptic connections received by this cell
}

proc connect_sections() { local i
  	connect dend[0](0), soma(1)
  	connect dend[1](0), soma(1)
  	connect axon(0), soma(0)
}

proc size_sections() {
	/*soma[0] {L=20 diam=10}
	dend[0] {L=250 diam=3}
	dend[1] {L=250 diam=3}
	axon[0] {L=150 diam=1.5}*/
NumSoma=1
NumApical=0
NumBasal=2
NumAxon=1
	
	soma[0] {pt3dclear()
		pt3dadd(0.0, 0.0, 0.0, 10.0) // distance from (0,0,0) = 0
		pt3dadd(0.0, 10.0, 0.0, 10.0) // distance from (0,0,0) = 10
		pt3dadd(0.0, 20.0, 0.0, 10.0) // distance from (0,0,0) = 20
	}
	dend[0] {pt3dclear()
		pt3dadd(0.0, 20.0, 0.0, 3.0) // distance from (0,0,0) = 0
		pt3dadd(100.0, 120.0, 0.0, 3.0) // distance from (0,0,0) = 10
		pt3dadd(177.0, 197.0, 0.0, 3.0) // distance from (0,0,0) = 20
	}
	dend[1] {pt3dclear()
		pt3dadd(0.0, 20.0, 0.0, 3.0) // distance from (0,0,0) = 0
		pt3dadd(-100.0, 120.0, 0.0, 3.0) // distance from (0,0,0) = 10
		pt3dadd(-177.0, 197.0, 0.0, 3.0) // distance from (0,0,0) = 20
	}
	axon[0] {pt3dclear()
		pt3dadd(0.0, 0.0, 0.0, 1.5) // distance from (0,0,0) = 0
		pt3dadd(0.0, -75.0, 0.0, 1.5) // distance from (0,0,0) = 10
		pt3dadd(0.0, -150.0, 0.0, 1.5) // distance from (0,0,0) = 20
	}
}

objref all, basal_list, apical_list, dendrite_list, soma_list, axon_list
proc append_sections() { local i
	objref all, basal_list, apical_list, dendrite_list, soma_list, axon_list

	all = new SectionList()
	basal_list = new SectionList()
	apical_list = new SectionList()
	soma_list = new SectionList()
	axon_list = new SectionList()
	dendrite_list = new SectionList()

    	soma all.append()
    	soma soma_list.append()
    	dend[0] all.append()
    	dend[0] basal_list.append()
    	dend[0] dendrite_list.append()
    	dend[1] all.append()
    	dend[1] basal_list.append()
    	dend[1] dendrite_list.append()
    	axon all.append()
    	axon axon_list.append()
}


external lambda_f
proc set_nseg() {
  	forsec all { nseg = int((L/(0.1*lambda_f(100))+.9)/2)*2 + 1  }
}



proc mechinit() {	
	// Temperature of simulation
	celsius = 34.0  

	Vrest = -67
	
	Rm = 20000*5
	
	gH = 0.0005
	
	gKvAsoma = 0.0165*.3
	gKvAdend = 0.004*.7
	
	// *2.3 gives 2x frequency & no depol. block
	gKvEaxon =  0.05104*2.3
	gKvEsoma =  0.0319*2.3
	gKvEdend =  2*0.023*2.3
	
	gNasoma = 0.0107
	gNadend = 2*0.0117
	gNaaxon = 0.01712
	
	eleak = -67	
}

proc insert_mechs() {
  	soma {
		insert ch_KvAolm
    		gmax_ch_KvAolm = gKvAsoma
		insert ch_HCNolm
			gmax_ch_HCNolm = gH 
		insert ch_Kdrfast  // ch_Kvsoma
			gmax_ch_Kdrfast = gKvEsoma 
		insert ch_Nav // ch_Navsoma
			gmax_ch_Nav = gNasoma
		insert ch_leak
			gmax_ch_leak = 1/Rm
			e_ch_leak = eleak  	
	}

  	dend[0] {
		insert ch_KvAolm
    		gmax_ch_KvAolm = gKvAdend
		insert ch_Kdrfast // ch_Kvdend
			gmax_ch_Kdrfast = gKvEdend
		insert ch_Nav // ch_Navdend
			gmax_ch_Nav = gNadend
		insert ch_leak
			gmax_ch_leak = 1/Rm
			e_ch_leak = eleak  	
  	}

  	dend[1] {
		insert ch_KvAolm
    		gmax_ch_KvAolm = gKvAdend
		insert ch_Kdrfast // ch_Kvdend
			gmax_ch_Kdrfast = gKvEdend
		insert ch_Nav // ch_Navdend
			gmax_ch_Nav = gNadend
		insert ch_leak
			gmax_ch_leak = 1/Rm
			e_ch_leak = eleak  	
  	}
  
  	axon {
		insert ch_Kdrfast // ch_Kvsoma //ch_Kvaxon
			gmax_ch_Kdrfast = gKvEaxon
		insert ch_Nav // ch_Navsoma //ch_Navaxon
			gmax_ch_Nav = gNaaxon
		insert ch_leak
			gmax_ch_leak = 1/Rm
			e_ch_leak = eleak  	
  	}
}

proc set_chanparams() {
	forsec all {
		Ra = 150	// Ra = Axial resistivity in ohm-cm. Ra is a
					//  section variable that must be set for each
					//  section. Default is 35.4.

		cm = 1.3	// capacitance in uF/cm^2. default = 1.0
		//ena = 55
		//ek = -90
	}  // make catau slower70e-3 	cao=2 cai=50.e-6 
}


	proc connect_pre() {  // $o1 target point process, $o2 returned NetCon
	soma $o2 = new NetCon (&v(1), $o1)
			$o2.threshold = -20

	}

	func is_art()  { return 0 }

proc position(){ local i
	forall {
		for i = 0, n3d()-1 {
			pt3dchange(i, $1-x+x3d(i), $2-y+y3d(i), $3-z+z3d(i), diam3d(i))
		}
	}
	x = $1  y = $2  z = $3	
}

proc get_root() {local i localobj sref
	rootlist = new SectionList()
	rootlist.allroots()
	i=0
	forsec all {
		sref = new SectionRef()
		if (sref.has_parent==0) {
			myroot = secname()
			i=i+1
		}
		for(x,0) {
			if (diam(x) <=0.01) print "WARNING: tiny diameter of ",  diam(x), " um at ", secname(), ", point ", x, "!"
			if (diam3d(x) <=0.01) print "WARNING: tiny 3d diameter of ", diam3d(x), " um at ", secname(), ", point ", x, "!"
		}
		if (L <=0.001) print "WARNING: tiny length of ", L, " um at ", secname(), "!"
	}
	if (i>1) {
		print "WARNING: cell ", gid, " has ", i, " root sections!"
	}
}

strdef myStr

objref newSecRef, syn
proc define_synapses() {
	ind = $1
	i = 0

	access soma[0]
	{distance()}

	for celltype = 0, numCellTypes-1 {
		templist = new List ()
		for r=0, cellType[ind].SynList[celltype].count()-1 {
			execute(cellType[ind].SynList[celltype].object(r).NewSynStr, this) // sets newSecRef
						
			forsec newSecRef {		
				for (x,0) {
					execute(cellType[ind].SynList[celltype].object(r).CondStr, this)
					 if (y==1) {
						execute(cellType[ind].SynList[celltype].object(r).SynStr, this)
						if (cellType[ind].SynList[celltype].object(r).GABAabFlag==0) {
							syn.tau1 = cellType[ind].SynList[celltype].object(r).tau1
							syn.tau2 = cellType[ind].SynList[celltype].object(r).tau2
							syn.e = cellType[ind].SynList[celltype].object(r).efirst
							if (strcmp(cellType[ind].SynList[celltype].object(r).SynType,"MyExp2Sidnw")==0) {
								execute(cellType[ind].SynList[celltype].object(r).Scaling, this)
							}
						} else {
							syn.tau1a = cellType[ind].SynList[celltype].object(r).tau1a
							syn.tau2a = cellType[ind].SynList[celltype].object(r).tau2a
							syn.ea = cellType[ind].SynList[celltype].object(r).ea
							syn.tau1b = cellType[ind].SynList[celltype].object(r).tau1b
							syn.tau2b = cellType[ind].SynList[celltype].object(r).tau2b
							syn.eb = cellType[ind].SynList[celltype].object(r).eb
						}
						syn.sid = i
						templist.append(syn)
						i = i + 1
					}
				}
			}
		}
		pre_list.append(templist)
		findme = 1
	}
}
endtemplate olmcell