// CA1 Pyramidal cell template (weak bAP)
// Geometry: 17 sections
// Morphology: from Cutsuridis et al., 2010
// Active properties: from Migliore et al., 2018
// Author: Matus Tomko
// Mail: matus.tomko __at__ fmph.uniba.sk
// Optimized using HippoUnit (Saray et al., 2020)

begintemplate CA1_PC_Tomko
public is_art
public init, topol, basic_shape, subsets, geom, biophys

public soma, radTprox1, radTprox2, radTmed1, radTmed2, radTdist1, radTdist2, lm_thick2, lm_medium2, lm_thin2, axon
public lm_thick1, lm_medium1, lm_thin1, oriprox1, oridist1_1, oridist1_2, oriprox2, oridist2_1, oridist2_2
public rad_t1, rad_t2, rad_t3

public all, somatic, apical, basal, axonal, oblique_sec_list, trunk_sec_list
objref all, somatic, apical, basal, axonal, oblique_sec_list, trunk_sec_list
objref this, CellRef

create soma[1], radTprox1, radTprox2, radTmed1, radTmed2, radTdist1, radTdist2, lm_thick2, lm_medium2, lm_thin2, axon
create rad_t1, rad_t2, rad_t3
create lm_thick1, lm_medium1, lm_thin1, oriprox1, oridist1_1, oridist1_2, oriprox2, oridist2_1, oridist2_2

proc init() {
  topol()
  basic_shape()
  subsets()
  geom()
  geom_nseg()
  insertChannel()
  biophys()
}

proc topol() { local i
  connect radTprox1(0), soma(1)
  connect radTprox2(0), radTprox1(1)
  connect radTmed1(0), radTprox2(1)
  connect radTmed2(0), radTmed1(1)
  connect radTdist1(0), radTmed2(1)
  connect radTdist2(0), radTdist1(1)

  connect rad_t1(0), radTprox1(1)
  connect rad_t2(0), radTmed1(1)
  connect rad_t3(0), radTdist1(1)

  connect lm_thick2(0), radTdist2(1)
  connect lm_medium2(0), lm_thick2(1)
  connect lm_thin2(0), lm_medium2(1)
  connect lm_thick1(0), radTdist2(1)
  connect lm_medium1(0), lm_thick1(1)
  connect lm_thin1(0), lm_medium1(1)

  connect oriprox1(0), soma(0)
  connect oridist1_1(0), oriprox1(1)
  connect oridist1_2(0), oriprox1(1)
  connect oriprox2(0), soma(1)
  connect oridist2_1(0), oriprox2(1)
  connect oridist2_2(0), oriprox2(1)
  connect axon(0), soma(1)
}

proc basic_shape() {
  soma {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(15, 0, 0, 1)}

  radTprox1 {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(15, 15, 0, 1)}
  radTprox2 {pt3dclear() pt3dadd(15, 15, 0, 1) pt3dadd(15, 30, 0, 1)}
  radTmed1 {pt3dclear() pt3dadd(15, 30, 0, 1) pt3dadd(15, 45, 0, 1)}
  radTmed2 {pt3dclear() pt3dadd(15, 45, 0, 1) pt3dadd(15, 60, 0, 1)}
  radTdist1 {pt3dclear() pt3dadd(15, 60, 0, 1) pt3dadd(15, 75, 0, 1)}
  radTdist2 {pt3dclear() pt3dadd(15, 75, 0, 1) pt3dadd(15, 90, 0, 1)}

  rad_t1 {pt3dclear() pt3dadd(15, 15, 0, 1) pt3dadd(75, 45, 0, 1)}
  rad_t2 {pt3dclear() pt3dadd(15, 45, 0, 1) pt3dadd(-45, 75, 0, 1)}
  rad_t3 {pt3dclear() pt3dadd(15, 75, 0, 1) pt3dadd(75, 105, 0, 1)}

  lm_thick2 {pt3dclear() pt3dadd(15, 90, 0, 1) pt3dadd(45, 105, 0, 1)}
  lm_medium2 {pt3dclear() pt3dadd(45, 105, 0, 1) pt3dadd(75, 120, 0, 1)}
  lm_thin2 {pt3dclear() pt3dadd(75, 120, 0, 1) pt3dadd(105, 135, 0, 1)}
  lm_thick1 {pt3dclear() pt3dadd(15, 90, 0, 1) pt3dadd(-15, 105, 0, 1)}
  lm_medium1 {pt3dclear() pt3dadd(-15, 105, 0, 1) pt3dadd(-45, 120, 0, 1)}
  lm_thin1 {pt3dclear() pt3dadd(-45, 120, 0, 1) pt3dadd(-70, 135, 0, 1)}

  oriprox1 {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(-45, -30, 0, 1)}
  oridist1_1 {pt3dclear() pt3dadd(-45, -30, 0, 1) pt3dadd(-75, -60, 0, 1)}
  oridist1_2 {pt3dclear() pt3dadd(-45, -30, 0, 1) pt3dadd(-85, -30, 0, 1)}
  oriprox2 {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(60, -30, 0, 1)}
  oridist2_1 {pt3dclear() pt3dadd(60, -30, 0, 1) pt3dadd(105, -60, 0, 1)}
  oridist2_2 {pt3dclear() pt3dadd(60, -30, 0, 1) pt3dadd(100, -30, 0, 1)}

  axon {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(15, -150, 0, 1)}
}

proc subsets() {
  all = new SectionList()
  soma all.append()
  radTprox1 all.append()
  radTprox2 all.append()
  radTmed1 all.append()
  radTmed2 all.append()
  radTdist1 all.append()
  radTdist2 all.append()
  rad_t1 all.append()
  rad_t2 all.append()
  rad_t3 all.append()
  lm_thick2 all.append()
  lm_medium2 all.append()
  lm_thin2 all.append()
  lm_thick1 all.append()
  lm_medium1 all.append()
  lm_thin1 all.append()
  oriprox1 all.append()
  oridist1_1 all.append()
  oridist1_2 all.append()
  oriprox2 all.append()
  oridist2_1 all.append()
  oridist2_2 all.append()
  axon all.append()

  apical = new SectionList()
  radTprox1 apical.append()
  radTprox2 apical.append()
  radTmed1 apical.append()
  radTmed2 apical.append()
  radTdist1 apical.append()
  radTdist2 apical.append()
  rad_t1 apical.append()
  rad_t2 apical.append()
  rad_t3 apical.append()
  lm_thick2 apical.append()
  lm_medium2 apical.append()
  lm_thin2 apical.append()
  lm_thick1 apical.append()
  lm_medium1 apical.append()
  lm_thin1 apical.append()

  basal = new SectionList()
  oriprox1 basal.append()
  oridist1_1 basal.append()
  oridist1_2 basal.append()
  oriprox2 basal.append()
  oridist2_1 basal.append()
  oridist2_2 basal.append()

  somatic = new SectionList()
  soma somatic.append()

  axonal = new SectionList()
  axon axonal.append()

  trunk_sec_list = new SectionList()
  radTprox1 trunk_sec_list.append()
  radTprox2 trunk_sec_list.append()
  radTmed1 trunk_sec_list.append()
  radTmed2 trunk_sec_list.append()
  radTdist1 trunk_sec_list.append()
  radTdist2 trunk_sec_list.append()

  oblique_sec_list = new SectionList()
  rad_t1 oblique_sec_list.append()
  rad_t2 oblique_sec_list.append()
  rad_t3 oblique_sec_list.append()
}

proc geom() {
  soma {  L = 10  diam = 10  }

  // SR is first 500um of apical dendrite
  radTprox1 {  L = 50  diam = 4  }
  radTprox2 {  L = 50  diam = 4  }
  radTmed1 {  L = 50  diam = 3  }
  radTmed2 {  L = 50  diam = 3  }
  radTdist1 {  L = 100  diam = 2  }
  radTdist2 {  L = 100  diam = 2  }

  // SR thin dendrites
  rad_t1 {  L = 150  diam = 1  }
  rad_t2 {  L = 150  diam = 1  }
  rad_t3 {  L = 150  diam = 1  }

  // OLM is final 300um of apical dendrite
  lm_thick2 {  L = 100  diam = 2  }
  lm_medium2 {  L = 100  diam = 1.5  }
  lm_thin2 {  L = 50  diam = 1  }
  lm_thick1 {  L = 100  diam = 2  }
  lm_medium1 {  L = 100  diam = 1.5  }
  lm_thin1 {  L = 50  diam = 1  }

  // Basal dendrites extend 300 um
  oriprox1 {  L = 100  diam = 2  }
  oridist1_1 {  L = 200  diam = 1.5  }
  oridist1_2 {  L = 200  diam = 1.5  }
  oriprox2 {  L = 100  diam = 2  }
  oridist2_1 {  L = 200  diam = 1.5  }
  oridist2_2 {  L = 200  diam = 1.5  }

  // Short section of axon
  axon {  L = 150  diam = 1  }
}


proc geom_nseg() {
  forsec all {
	nseg = 1 + 2*int(L/40)
  }
}

proc distribute_distance(){local x localobj sl
  strdef stmp, distfunc, mech

  sl = $o1
  mech = $s2
  distfunc = $s3
  soma distance(0, 0.5)
  sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc)
  forsec sl for(x, 0) {
    sprint(stmp, distfunc, secname(), x, distance(x))
    execute(stmp)
  }
}

proc insertChannel() {
    forsec all {
        insert pas
        insert kdr
        insert nax
    }

    forsec somatic {
        insert kmb
        insert kap
        insert hd
        insert can
        insert cal
        insert cat
        insert kca
        insert cagk
        insert cacum
    }

    forsec apical {
        insert kad
        insert hd
        insert can
        insert cal
        insert cat
        insert kca
        insert cagk
        insert cacum
    }

    forsec basal {
        insert kad
        insert hd
        insert can
        insert cal
        insert cat
        insert kca
        insert cagk
        insert cacum
    }

    forsec this.axonal {
        insert kmb
        insert kap
    }

}
proc biophys() {

    celsius = 35
    v_init = -65

    forsec all {
    cm = 1
    ena = 50
    ek = -90
    }

    // opt for depolarization block
    forsec somatic {
        gkabar_kap = 0.0075
        gbar_kmb = 0.001
        gkdrbar_kdr = 0.0015
        gbar_nax = 0.035
        gcalbar_cal =  0.0005
        gcanbar_can = 2.2618914062501833e-06
        gcatbar_cat =  0.00005
        gbar_kca = 0.0015
        gbar_cagk = 4.4820097108998517e-05
        Ra = 115.3957607556371
        g_pas = 9.031387191839301e-05
    }

    forsec axonal {
        gbar_nax = 0.035
        gkdrbar_kdr = 0.011664045469379856
        gbar_kmb = 0.026473888790212396
        gkabar_kap = 0.1636942175250268
        Ra = 85.202399381150826
        g_pas = 0.00012898002027660884
        e_pas = -79.917091935442244
    }

    forsec apical {
        gkdrbar_kdr = 0.0043036502438625682
        gbar_nax = 0.038280628170345957
        gcalbar_cal = 8.0324964335287e-06
        gcanbar_can = 2.2618914062501833e-06
        gcatbar_cat = 1.184948741542104e-06
        gbar_kca = 9.0311387916396796e-05
        gbar_cagk = 4.4820097108998517e-05
        Ra = 115.3957607556371
        g_pas = 9.031387191839301e-05
    }

    //opt for backpropagation
    forsec trunk_sec_list {
        gkdrbar_kdr = 0.02
        gbar_nax = 0.025
        gcalbar_cal = 8.0324964335287e-06
        gcanbar_can = 2.2618914062501833e-06
        gcatbar_cat = 1.184948741542104e-06
        gbar_kca = 9.0311387916396796e-05
        gbar_cagk = 4.4820097108998517e-05
        Ra = 115.3957607556371
        g_pas = 9.031387191839301e-05
    }

    forsec basal {
        gkdrbar_kdr = 0.0043036502438625682
        gbar_nax = 0.038280628170345957
        gcalbar_cal = 8.0324964335287e-06
        gcanbar_can = 2.2618914062501833e-06
        gcatbar_cat = 1.184948741542104e-06
        gbar_kca = 9.0311387916396796e-05
        gbar_cagk = 4.4820097108998517e-05
        Ra = 115.3957607556371
        g_pas = 9.031387191839301e-05
    }

    distribute_distance(apical, "ghdbar_hd", "(1. + 3./100. * %.17g)*1.9042409723832741e-05")
    distribute_distance(apical, "e_pas", "(-65.726902768520958-5*%.17g/150)")
    distribute_distance(apical, "gkabar_kad", "(15./(1. + exp((300-%.17g)/50)))* 0.012921529390557651 ")
    distribute_distance(basal, "ghdbar_hd", "(1. + 3./100. * %.17g)*1.9042409723832741e-05")
    distribute_distance(basal, "e_pas", "(-65.726902768520958-5*%.17g/150)")
    distribute_distance(basal, "gkabar_kad", "(15./(1. + exp((300-%.17g)/50)))*0.012921529390557651")
    distribute_distance(somatic, "ghdbar_hd", "(1. + 3./100. * %.17g)*1.9042409723832741e-05")
    distribute_distance(somatic, "e_pas", "(-65.726902768520958-5*%.17g/150)")

    radTprox1 {gkabar_kad = 0.1}
    radTprox2 {gkabar_kad = 0.1}
    rad_t1 {gkabar_kad = 0.1}
    radTmed1 {gkabar_kad = 0.15}
    radTmed2 {gkabar_kad = 0.15}
    rad_t2 {gkabar_kad = 0.1
    gbar_nax = 0.038
    gkdrbar_kdr = 0.002}
    radTdist1 {gkabar_kad = 0.2}
    radTdist2 {gkabar_kad = 0.2}
    rad_t3 {gkabar_kad = 0.25}
}


func is_art() { return 0 }

endtemplate CA1_PC_Tomko