postprocess_cells.py 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690
  1. #!/usr/bin/env python3
  2. """
  3. Post process and add biophysics to cells.
  4. We make any updates to the morphology, and add biophysics.
  5. File: NeuroML2/postprocess_cells.py
  6. Copyright 2022 Ankur Sinha
  7. Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
  8. """
  9. import random
  10. import sys
  11. import neuroml
  12. import numpy
  13. from neuroml.loaders import read_neuroml2_file
  14. from neuroml.neuro_lex_ids import neuro_lex_ids
  15. from pyneuroml.analysis import generate_current_vs_frequency_curve
  16. from pyneuroml.lems.LEMSSimulation import LEMSSimulation
  17. from pyneuroml.plot.PlotMorphology import plot_2D
  18. from pyneuroml.pynml import run_lems_with_jneuroml_neuron, write_neuroml2_file
  19. random.seed(1412)
  20. def load_and_setup_cell(cellname: str):
  21. """Load a cell, and clean it to prepare it for further modifications.
  22. These operations are common for all cells.
  23. :param cellname: name of cell.
  24. the file containing the cell should then be <cell>.morph.cell.nml
  25. :returns: document with cell
  26. :rtype: neuroml.NeuroMLDocument
  27. """
  28. celldoc = read_neuroml2_file(
  29. f"{cellname}.morph.cell.nml"
  30. ) # type: neuroml.NeuroMLDocument
  31. cell = celldoc.cells[0] # type: neuroml.Cell
  32. celldoc.networks = []
  33. cell.id = cellname
  34. cell.notes = cell.notes.replace("NeuronTemplate_0_0", cellname)
  35. cell.notes += ". Reference: Yao, H. K.; Guet-McCreight, A.; Mazza, F.; Moradi Chameh, H.; Prevot, T. D.; Griffiths, J. D.; Tripathy, S. J.; Valiante, T. A.; Sibille, E. & Hay, E. Reduced inhibition in depression impairs stimulus processing in human cortical microcircuits Cell Reports, Elsevier, 2022, 38"
  36. # create default groups if they don't exist
  37. [
  38. default_all_group,
  39. default_soma_group,
  40. default_dendrite_group,
  41. default_axon_group,
  42. ] = cell.setup_default_segment_groups(
  43. use_convention=True,
  44. default_groups=["all", "soma_group", "dendrite_group", "axon_group"],
  45. )
  46. # populate default groups
  47. for sg in cell.morphology.segment_groups:
  48. if "soma" in sg.id and sg.id != "soma_group":
  49. default_soma_group.add(neuroml.Include(segment_groups=sg.id))
  50. if "axon" in sg.id and sg.id != "axon_group":
  51. default_axon_group.add(neuroml.Include(segment_groups=sg.id))
  52. if "dend" in sg.id and sg.id != "dendrite_group":
  53. default_dendrite_group.add(neuroml.Include(segment_groups=sg.id))
  54. cell.optimise_segment_groups()
  55. return celldoc
  56. def postprocess_HL23PYR():
  57. """Post process HL23PYR and add biophysics."""
  58. cellname = "HL23PYR"
  59. celldoc = load_and_setup_cell(cellname)
  60. cell = celldoc.cells[0] # type: neuroml.Cell
  61. # apical dendrites are in groups called apic_
  62. # basal dendrites are in groups called dend_
  63. # populate the complete dendrite group, and new groups for all apical and
  64. # basal dendrites
  65. default_dendrite_group = cell.get_segment_group("dendrite_group")
  66. basal_group = cell.add_segment_group(
  67. "basal_dendrite_group",
  68. neuro_lex_id=neuro_lex_ids["dend"],
  69. notes="Basal dendrites",
  70. )
  71. apical_group = cell.add_segment_group(
  72. "apical_dendrite_group",
  73. neuro_lex_id=neuro_lex_ids["dend"],
  74. notes="Apical dendrite_group",
  75. )
  76. # create new global myelin group
  77. myelin_group = cell.add_segment_group("myelin_group", notes="Myelin group")
  78. for sg in cell.morphology.segment_groups:
  79. if "apic_" in sg.id:
  80. apical_group.add(neuroml.Include(segment_groups=sg.id))
  81. if "dend_" in sg.id:
  82. basal_group.add(neuroml.Include(segment_groups=sg.id))
  83. if "myelin_" in sg.id and sg.id != "myelin_group":
  84. myelin_group.add(neuroml.Include(segment_groups=sg.id))
  85. # myelin groups are not included in the all segment group when adding
  86. # biophys
  87. all_segment_group = cell.get_segment_group("all") # type neuroml.SegmentGroup
  88. all_minus_myelin = cell.add_segment_group(
  89. "all_minus_myelin", notes="All without myelin"
  90. )
  91. for inc in all_segment_group.includes:
  92. if "myelin" not in inc.segment_groups:
  93. all_minus_myelin.includes.append(inc)
  94. for sg in all_segment_group.members:
  95. if "myelin" not in sg.segment:
  96. all_minus_myelin.members.append(sg)
  97. # optimise dendrite group
  98. default_dendrite_group.includes = []
  99. default_dendrite_group.includes.append(
  100. neuroml.Include(segment_groups=apical_group.id)
  101. )
  102. default_dendrite_group.includes.append(
  103. neuroml.Include(segment_groups=basal_group.id)
  104. )
  105. cell.optimise_segment_groups()
  106. cell.reorder_segment_groups()
  107. # biophysics
  108. # include calcium dynamics component
  109. celldoc.add(neuroml.IncludeType(href="CaDynamics_E2_NML2.nml"), validate=False)
  110. # all
  111. cell.add_channel_density(
  112. nml_cell_doc=celldoc,
  113. cd_id="pas",
  114. ion_channel="pas",
  115. cond_density="0.0000954 S_per_cm2",
  116. erev="-80 mV",
  117. group_id="all_minus_myelin",
  118. ion="non_specific",
  119. ion_chan_def_file="channels/pas.channel.nml",
  120. )
  121. cell.set_resistivity("0.1 kohm_cm", group_id="all_minus_myelin")
  122. cell.set_specific_capacitance("1 uF_per_cm2", group_id="all_minus_myelin")
  123. cell.set_init_memb_potential("-80mV")
  124. # 10mV is default for Neuron spike threshold in NetCon
  125. # https://www.neuron.yale.edu/neuron/static/py_doc/modelspec/programmatic/network/netcon.html
  126. cell.biophysical_properties.membrane_properties.spike_threshes.append(neuroml.SpikeThresh(value="10mV", segment_groups='all'))
  127. # myelin
  128. cell.set_specific_capacitance("0.02 uF_per_cm2", group_id="myelin_group")
  129. cell.set_resistivity("0.1 kohm_cm", group_id="myelin_group")
  130. # write passive cell
  131. write_neuroml2_file(celldoc, f"{cellname}.pas.cell.nml")
  132. # somatic
  133. soma_group = cell.get_segment_group("soma_group")
  134. sgid = soma_group.id
  135. print(f"Adding channels to {sgid}")
  136. # K
  137. cell.add_channel_density(
  138. nml_cell_doc=celldoc,
  139. cd_id="SK_somatic",
  140. ion_channel="SK",
  141. cond_density="0.000853 S_per_cm2",
  142. erev="-85 mV",
  143. group_id=sgid,
  144. ion="k",
  145. ion_chan_def_file="channels/SK.channel.nml",
  146. )
  147. cell.add_channel_density(
  148. nml_cell_doc=celldoc,
  149. cd_id="K_T_somatic",
  150. ion_channel="K_T",
  151. cond_density="0.0605 S_per_cm2",
  152. erev="-85 mV",
  153. group_id=sgid,
  154. ion="k",
  155. ion_chan_def_file="channels/K_T.channel.nml",
  156. )
  157. cell.add_channel_density(
  158. nml_cell_doc=celldoc,
  159. cd_id="K_P_somatic",
  160. ion_channel="K_P",
  161. cond_density="0.000208 S_per_cm2",
  162. erev="-85 mV",
  163. group_id=sgid,
  164. ion="k",
  165. ion_chan_def_file="channels/K_P.channel.nml",
  166. )
  167. cell.add_channel_density(
  168. nml_cell_doc=celldoc,
  169. cd_id="Kv3_1_somatic",
  170. ion_channel="Kv3_1",
  171. cond_density="0.0424 S_per_cm2",
  172. erev="-85 mV",
  173. group_id=sgid,
  174. ion="k",
  175. ion_chan_def_file="channels/Kv3_1.channel.nml",
  176. )
  177. cell.add_channel_density(
  178. nml_cell_doc=celldoc,
  179. cd_id="Ih_somatic",
  180. ion_channel="Ih",
  181. cond_density="0.000148 S_per_cm2",
  182. erev="-45 mV",
  183. group_id=sgid,
  184. ion="hcn",
  185. ion_chan_def_file="channels/Ih.channel.nml",
  186. )
  187. cell.add_channel_density(
  188. nml_cell_doc=celldoc,
  189. cd_id="Im_somatic",
  190. ion_channel="Im",
  191. cond_density="0.000306 S_per_cm2",
  192. erev="-85 mV",
  193. group_id=sgid,
  194. ion="k",
  195. ion_chan_def_file="channels/Im.channel.nml",
  196. )
  197. # Na
  198. cell.add_channel_density(
  199. nml_cell_doc=celldoc,
  200. cd_id="NaTg_somatic",
  201. ion_channel="NaTg_PYR_somatic",
  202. cond_density="0.272 S_per_cm2",
  203. erev="50 mV",
  204. group_id=sgid,
  205. ion="na",
  206. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  207. )
  208. # Ca
  209. # external concentration is set to defaults that NEURON
  210. # starts with
  211. # internal concentration is set to minCai in mod file
  212. cell.add_intracellular_property(
  213. "Species",
  214. validate=False,
  215. id="ca",
  216. concentration_model="CaDynamics_E2_NML2_PYR_somatic",
  217. ion="ca",
  218. initial_concentration="1e-4 mM",
  219. initial_ext_concentration="2.0E-6 mol_per_cm3",
  220. segment_groups=sgid,
  221. )
  222. # https://www.neuron.yale.edu/neuron/static/new_doc/modelspec/programmatic/ions.html
  223. cell.add_channel_density_v(
  224. "ChannelDensityNernst",
  225. nml_cell_doc=celldoc,
  226. id="Ca_HVA_somatic",
  227. ion_channel="Ca_HVA",
  228. cond_density="0.00155 S_per_cm2",
  229. segment_groups=sgid,
  230. ion="ca",
  231. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  232. )
  233. cell.add_channel_density_v(
  234. "ChannelDensityNernst",
  235. nml_cell_doc=celldoc,
  236. id="Ca_LVA_somatic",
  237. ion_channel="Ca_LVA",
  238. cond_density="0.00296 S_per_cm2",
  239. segment_groups=sgid,
  240. ion="ca",
  241. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  242. )
  243. # Apical
  244. sg = cell.get_segment_group("apical_dendrite_group")
  245. cell.set_specific_capacitance("2 uF_per_cm2", group_id=sg.id)
  246. # Add parameter that we use to distribute Ih
  247. sg.add(
  248. "InhomogeneousParameter",
  249. id="PathLengthOverApicDends",
  250. variable="p",
  251. metric="Path Length from root",
  252. proximal=sg.component_factory("ProximalDetails", translation_start="0"),
  253. )
  254. # distribute Ih
  255. cdnonuniform = cell.add_channel_density_v(
  256. "ChannelDensityNonUniform",
  257. nml_cell_doc=celldoc,
  258. id="Ih_apical",
  259. ion_channel="Ih",
  260. ion="hcn",
  261. erev="-45 mV",
  262. )
  263. varparam = cdnonuniform.add(
  264. "VariableParameter",
  265. parameter="condDensity",
  266. segment_groups=sg.id,
  267. validate=False,
  268. )
  269. # TODO: clarify unit conversions
  270. # 606.3464 is the value of getLongestBranch("apic")
  271. # run test_HL23PYR.hoc, and then run:
  272. # > access HL23PYR.apic
  273. # > HL23PYR.soma distance()
  274. # > HL23PYR.getLongestBranch("apic")
  275. inhomogeneous_value = varparam.add(
  276. "InhomogeneousValue",
  277. inhomogeneous_parameters="PathLengthOverApicDends",
  278. value="1E9 * (0.148 * 1E-8) * ((2.087 * exp( 3.6161 * (p/606.3464))) - 0.8696)",
  279. )
  280. # Basal
  281. basal_group = cell.get_segment_group("basal_dendrite_group")
  282. sgid = basal_group.id
  283. cell.set_specific_capacitance("2 uF_per_cm2", group_id=sgid)
  284. cell.add_channel_density(
  285. nml_cell_doc=celldoc,
  286. cd_id="Ih_basal",
  287. ion_channel="Ih",
  288. cond_density="0.000000709 S_per_cm2",
  289. erev="-45 mV",
  290. group_id=sgid,
  291. ion="hcn",
  292. ion_chan_def_file="channels/Ih.channel.nml",
  293. )
  294. # Axonal
  295. axon_group = cell.get_segment_group("axon_group")
  296. sgid = axon_group.id
  297. print(f"Adding channels to {sgid}")
  298. # K
  299. cell.add_channel_density(
  300. nml_cell_doc=celldoc,
  301. cd_id="SK_axonal",
  302. ion_channel="SK",
  303. cond_density="0.0145 S_per_cm2",
  304. erev="-85 mV",
  305. group_id=sgid,
  306. ion="k",
  307. ion_chan_def_file="channels/SK.channel.nml",
  308. )
  309. cell.add_channel_density(
  310. nml_cell_doc=celldoc,
  311. cd_id="K_T_axonal",
  312. ion_channel="K_T",
  313. cond_density="0.0424 S_per_cm2",
  314. erev="-85 mV",
  315. group_id=sgid,
  316. ion="k",
  317. ion_chan_def_file="channels/K_T.channel.nml",
  318. )
  319. cell.add_channel_density(
  320. nml_cell_doc=celldoc,
  321. cd_id="K_P_axonal",
  322. ion_channel="K_P",
  323. cond_density="0.338 S_per_cm2",
  324. erev="-85 mV",
  325. group_id=sgid,
  326. ion="k",
  327. ion_chan_def_file="channels/K_P.channel.nml",
  328. )
  329. cell.add_channel_density(
  330. nml_cell_doc=celldoc,
  331. cd_id="Im_axonal",
  332. ion_channel="Im",
  333. cond_density="0.000 S_per_cm2",
  334. erev="-85 mV",
  335. group_id=sgid,
  336. ion="k",
  337. ion_chan_def_file="channels/Im.channel.nml",
  338. )
  339. cell.add_channel_density(
  340. nml_cell_doc=celldoc,
  341. cd_id="Kv3_1_axonal",
  342. ion_channel="Kv3_1",
  343. cond_density="0.941 S_per_cm2",
  344. erev="-85 mV",
  345. group_id=sgid,
  346. ion="k",
  347. ion_chan_def_file="channels/Kv3_1.channel.nml",
  348. )
  349. # Na
  350. cell.add_channel_density(
  351. nml_cell_doc=celldoc,
  352. cd_id="NaTg_axonal",
  353. ion_channel="NaTg_PYR_axonal",
  354. cond_density="1.38 S_per_cm2",
  355. erev="50 mV",
  356. group_id=sgid,
  357. ion="na",
  358. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  359. )
  360. cell.add_channel_density(
  361. nml_cell_doc=celldoc,
  362. cd_id="Nap_axonal",
  363. ion_channel="Nap",
  364. cond_density="0.00842 S_per_cm2",
  365. erev="50 mV",
  366. group_id=sgid,
  367. ion="na",
  368. ion_chan_def_file="channels/Nap.channel.nml",
  369. )
  370. # Ca
  371. cell.add_channel_density_v(
  372. "ChannelDensityNernst",
  373. nml_cell_doc=celldoc,
  374. id="Ca_HVA_axonal",
  375. ion_channel="Ca_HVA",
  376. cond_density="0.0003060000 S_per_cm2",
  377. segment_groups=sgid,
  378. ion="ca",
  379. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  380. )
  381. cell.add_channel_density_v(
  382. "ChannelDensityNernst",
  383. nml_cell_doc=celldoc,
  384. id="Ca_LVA_axonal",
  385. ion_channel="Ca_LVA",
  386. cond_density="0.0439000000 S_per_cm2",
  387. segment_groups=sgid,
  388. ion="ca",
  389. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  390. )
  391. # external concentration is set to defaults that NEURON
  392. # starts with
  393. # internal concentration is set to minCai in mod file
  394. cell.add_intracellular_property(
  395. "Species",
  396. validate=False,
  397. id="ca",
  398. concentration_model="CaDynamics_E2_NML2_PYR_axonal",
  399. ion="ca",
  400. initial_concentration="1e-4 mM",
  401. initial_ext_concentration="2.0E-6 mol_per_cm3",
  402. segment_groups=sgid,
  403. )
  404. cell.add_channel_density(
  405. nml_cell_doc=celldoc,
  406. cd_id="Ih_axonal",
  407. ion_channel="Ih",
  408. cond_density="0.00001 S_per_cm2",
  409. erev="-45 mV",
  410. group_id=sgid,
  411. ion="hcn",
  412. ion_chan_def_file="channels/Ih.channel.nml",
  413. )
  414. # L1 validation
  415. # cell.validate(recursive=True)
  416. # cell.summary(morph=False, biophys=True)
  417. # use pynml writer to also run L2 validation
  418. write_neuroml2_file(celldoc, f"{cellname}.cell.nml")
  419. def postprocess_HL23PV():
  420. """Post process HL23PV and add biophysics.
  421. Each cell needs its biophysics to be added, so we do each cell separately.
  422. """
  423. cellname = "HL23PV"
  424. celldoc = load_and_setup_cell(cellname)
  425. cell = celldoc.cells[0] # type: neuroml.Cell
  426. print("Segment groups:")
  427. for sg in cell.morphology.segment_groups:
  428. print(f"** {sg.id} **")
  429. print(cell.get_all_segments_in_group(sg.id))
  430. print()
  431. # biophysics
  432. # include calcium dynamics component
  433. celldoc.add(neuroml.IncludeType(href="CaDynamics_E2_NML2.nml"), validate=False)
  434. # all
  435. # Note: ion for passive channel must be "non_specific" for NEURON
  436. cell.add_channel_density(
  437. nml_cell_doc=celldoc,
  438. cd_id="pas",
  439. ion_channel="pas",
  440. cond_density="0.00011830111773572024 S_per_cm2",
  441. erev="-83.92924122901199 mV",
  442. group_id="all",
  443. ion="non_specific",
  444. ion_chan_def_file="channels/pas.channel.nml",
  445. )
  446. cell.set_resistivity("0.1 kohm_cm", group_id="all")
  447. cell.set_specific_capacitance("2 uF_per_cm2", group_id="all")
  448. cell.set_init_memb_potential("-80mV")
  449. # 10mV is default for Neuron spike threshold in NetCon
  450. # https://www.neuron.yale.edu/neuron/static/py_doc/modelspec/programmatic/network/netcon.html
  451. cell.biophysical_properties.membrane_properties.spike_threshes.append(neuroml.SpikeThresh(value="10mV", segment_groups='all'))
  452. # write passive cell before adding active properties
  453. write_neuroml2_file(celldoc, f"{cellname}.pas.cell.nml")
  454. cell.add_channel_density(
  455. nml_cell_doc=celldoc,
  456. cd_id="Ih",
  457. ion_channel="Ih",
  458. cond_density="2.7671764064314368e-05 S_per_cm2",
  459. erev="-45 mV",
  460. group_id="all",
  461. ion="hcn",
  462. ion_chan_def_file="channels/Ih.channel.nml",
  463. )
  464. # somatic
  465. soma_group = cell.get_segment_group("soma_group")
  466. sgid = soma_group.id
  467. print(f"Adding channels to {sgid}")
  468. # Na
  469. cell.add_channel_density(
  470. nml_cell_doc=celldoc,
  471. cd_id="NaTg_somatic",
  472. ion_channel="NaTg_PV",
  473. cond_density="0.49958525078702043 S_per_cm2",
  474. erev="50 mV",
  475. group_id=sgid,
  476. ion="na",
  477. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  478. )
  479. cell.add_channel_density(
  480. nml_cell_doc=celldoc,
  481. cd_id="Nap_somatic",
  482. ion_channel="Nap",
  483. cond_density="0.008795461417521086 S_per_cm2",
  484. erev="50 mV",
  485. group_id=sgid,
  486. ion="na",
  487. ion_chan_def_file="channels/Nap.channel.nml",
  488. )
  489. # K
  490. cell.add_channel_density(
  491. nml_cell_doc=celldoc,
  492. cd_id="K_P_somatic",
  493. ion_channel="K_P",
  494. cond_density="9.606092478937705e-06 S_per_cm2",
  495. erev="-85 mV",
  496. group_id=sgid,
  497. ion="k",
  498. ion_chan_def_file="channels/K_P.channel.nml",
  499. )
  500. cell.add_channel_density(
  501. nml_cell_doc=celldoc,
  502. cd_id="K_T_somatic",
  503. ion_channel="K_T",
  504. cond_density="0.0011701702607527396 S_per_cm2",
  505. erev="-85 mV",
  506. group_id=sgid,
  507. ion="k",
  508. ion_chan_def_file="channels/K_T.channel.nml",
  509. )
  510. cell.add_channel_density(
  511. nml_cell_doc=celldoc,
  512. cd_id="Kv3_1_somatic",
  513. ion_channel="Kv3_1",
  514. cond_density="2.9921080101237565 S_per_cm2",
  515. erev="-85 mV",
  516. group_id=sgid,
  517. ion="k",
  518. ion_chan_def_file="channels/Kv3_1.channel.nml",
  519. )
  520. cell.add_channel_density(
  521. nml_cell_doc=celldoc,
  522. cd_id="Im_somatic",
  523. ion_channel="Im",
  524. cond_density="0.04215865946497755 S_per_cm2",
  525. erev="-85 mV",
  526. group_id=sgid,
  527. ion="k",
  528. ion_chan_def_file="channels/Im.channel.nml",
  529. )
  530. cell.add_channel_density(
  531. nml_cell_doc=celldoc,
  532. cd_id="SK_somatic",
  533. ion_channel="SK",
  534. cond_density="3.7265770903193036e-06 S_per_cm2",
  535. erev="-85 mV",
  536. group_id=sgid,
  537. ion="k",
  538. ion_chan_def_file="channels/SK.channel.nml",
  539. )
  540. # Ca
  541. # external concentration is set to defaults that NEURON
  542. # starts with
  543. # internal concentration is set to minCai in mod file
  544. cell.add_intracellular_property(
  545. "Species",
  546. validate=False,
  547. id="ca",
  548. concentration_model="CaDynamics_E2_NML2_PV_somatic",
  549. ion="ca",
  550. initial_concentration="1e-4 mM",
  551. initial_ext_concentration="2.0E-6 mol_per_cm3",
  552. segment_groups=sgid,
  553. )
  554. # https://www.neuron.yale.edu/neuron/static/new_doc/modelspec/programmatic/ions.html
  555. cell.add_channel_density_v(
  556. "ChannelDensityNernst",
  557. nml_cell_doc=celldoc,
  558. id="Ca_HVA_somatic",
  559. ion_channel="Ca_HVA",
  560. cond_density="0.00017953651378188165 S_per_cm2",
  561. segment_groups=sgid,
  562. ion="ca",
  563. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  564. )
  565. cell.add_channel_density_v(
  566. "ChannelDensityNernst",
  567. nml_cell_doc=celldoc,
  568. id="Ca_LVA_somatic",
  569. ion_channel="Ca_LVA",
  570. cond_density="0.09250008555398015 S_per_cm2",
  571. segment_groups=sgid,
  572. ion="ca",
  573. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  574. )
  575. # axonal
  576. sgs = cell.get_segment_group("axon_group")
  577. sgid = sgs.id
  578. print(f"Adding channels to {sgid}")
  579. # Na
  580. cell.add_channel_density(
  581. nml_cell_doc=celldoc,
  582. cd_id="NaTg_axonal",
  583. ion_channel="NaTg_PV",
  584. cond_density="0.10914576408883477 S_per_cm2",
  585. erev="50 mV",
  586. group_id=sgid,
  587. ion="na",
  588. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  589. )
  590. cell.add_channel_density(
  591. nml_cell_doc=celldoc,
  592. cd_id="Nap_axonal",
  593. ion_channel="Nap",
  594. cond_density="0.001200899579358837 S_per_cm2",
  595. erev="50 mV",
  596. group_id=sgid,
  597. ion="na",
  598. ion_chan_def_file="channels/Nap.channel.nml",
  599. )
  600. # K
  601. cell.add_channel_density(
  602. nml_cell_doc=celldoc,
  603. cd_id="K_P_axonal",
  604. ion_channel="K_P",
  605. cond_density="0.6854776593761795 S_per_cm2",
  606. erev="-85 mV",
  607. group_id=sgid,
  608. ion="k",
  609. ion_chan_def_file="channels/K_P.channel.nml",
  610. )
  611. cell.add_channel_density(
  612. nml_cell_doc=celldoc,
  613. cd_id="K_T_axonal",
  614. ion_channel="K_T",
  615. cond_density="0.07603372775662909 S_per_cm2",
  616. erev="-85 mV",
  617. group_id=sgid,
  618. ion="k",
  619. ion_chan_def_file="channels/K_T.channel.nml",
  620. )
  621. cell.add_channel_density(
  622. nml_cell_doc=celldoc,
  623. cd_id="Kv3_1_axonal",
  624. ion_channel="Kv3_1",
  625. cond_density="2.988867483754507 S_per_cm2",
  626. erev="-85 mV",
  627. group_id=sgid,
  628. ion="k",
  629. ion_chan_def_file="channels/Kv3_1.channel.nml",
  630. )
  631. cell.add_channel_density(
  632. nml_cell_doc=celldoc,
  633. cd_id="Im_axonal",
  634. ion_channel="Im",
  635. cond_density="0.029587905136596156 S_per_cm2",
  636. erev="-85 mV",
  637. group_id=sgid,
  638. ion="k",
  639. ion_chan_def_file="channels/Im.channel.nml",
  640. )
  641. cell.add_channel_density(
  642. nml_cell_doc=celldoc,
  643. cd_id="SK_axonal",
  644. ion_channel="SK",
  645. cond_density="0.5121938998281017 S_per_cm2",
  646. erev="-85 mV",
  647. group_id=sgid,
  648. ion="k",
  649. ion_chan_def_file="channels/SK.channel.nml",
  650. )
  651. # Ca
  652. cell.add_channel_density_v(
  653. "ChannelDensityNernst",
  654. nml_cell_doc=celldoc,
  655. id="Ca_HVA_axonal",
  656. ion_channel="Ca_HVA",
  657. cond_density="0.002961469262723619 S_per_cm2",
  658. segment_groups=sgid,
  659. ion="ca",
  660. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  661. )
  662. cell.add_channel_density_v(
  663. "ChannelDensityNernst",
  664. nml_cell_doc=celldoc,
  665. id="Ca_LVA_axonal",
  666. ion_channel="Ca_LVA",
  667. cond_density="5.9457835817342756e-05 S_per_cm2",
  668. segment_groups=sgid,
  669. ion="ca",
  670. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  671. )
  672. # external concentration is set to defaults that NEURON
  673. # starts with
  674. # internal concentration is set to minCai in mod file
  675. cell.add_intracellular_property(
  676. "Species",
  677. validate=False,
  678. id="ca",
  679. concentration_model="CaDynamics_E2_NML2_PV_axonal",
  680. ion="ca",
  681. initial_concentration="1e-4 mM",
  682. initial_ext_concentration="2.0E-6 mol_per_cm3",
  683. segment_groups=sgid,
  684. )
  685. # L1 validation
  686. cell.validate(recursive=True)
  687. cell.summary(morph=True, biophys=True)
  688. # use pynml writer to also run L2 validation
  689. write_neuroml2_file(celldoc, f"{cellname}.cell.nml")
  690. def postprocess_HL23SST():
  691. """Post process HL23SST and add biophysics.
  692. Each cell needs its biophysics to be added, so we do each cell separately.
  693. """
  694. cellname = "HL23SST"
  695. celldoc = load_and_setup_cell(cellname)
  696. cell = celldoc.cells[0] # type: neuroml.Cell
  697. # basal dendrites are in groups called dend_
  698. # populate the complete dendrite group, and new groups for all apical and
  699. # basal dendrites
  700. default_dendrite_group = cell.get_segment_group("dendrite_group")
  701. basal_group = cell.add_segment_group(
  702. "basal_dendrite_group",
  703. neuro_lex_id=neuro_lex_ids["dend"],
  704. notes="Basal dendrites",
  705. )
  706. # create new global myelin group
  707. myelin_group = cell.add_segment_group("myelin_group", notes="Myelin group")
  708. for sg in cell.morphology.segment_groups:
  709. if "dend_" in sg.id:
  710. basal_group.add(neuroml.Include(segment_groups=sg.id))
  711. if "myelin_" in sg.id and sg.id != "myelin_group":
  712. myelin_group.add(neuroml.Include(segment_groups=sg.id))
  713. # myelin groups are not included in the all segment group when adding
  714. # biophys
  715. all_segment_group = cell.get_segment_group("all") # type neuroml.SegmentGroup
  716. all_minus_myelin = cell.add_segment_group(
  717. "all_minus_myelin", notes="All without myelin"
  718. )
  719. for inc in all_segment_group.includes:
  720. if "myelin" not in inc.segment_groups:
  721. all_minus_myelin.includes.append(inc)
  722. for sg in all_segment_group.members:
  723. if "myelin" not in sg.segment:
  724. all_minus_myelin.members.append(sg)
  725. # optimise dendrite group
  726. default_dendrite_group.includes = []
  727. default_dendrite_group.includes.append(
  728. neuroml.Include(segment_groups=basal_group.id)
  729. )
  730. cell.optimise_segment_groups()
  731. cell.reorder_segment_groups()
  732. print("Segment groups:")
  733. for sg in cell.morphology.segment_groups:
  734. print(f"** {sg.id} **")
  735. print(cell.get_all_segments_in_group(sg.id))
  736. print()
  737. # biophysics
  738. # include calcium dynamics component
  739. celldoc.add(neuroml.IncludeType(href="CaDynamics_E2_NML2.nml"), validate=False)
  740. # all
  741. # Note: ion for passive channel must be "non_specific" for NEURON
  742. cell.add_channel_density(
  743. nml_cell_doc=celldoc,
  744. cd_id="pas",
  745. ion_channel="pas",
  746. cond_density="0.0000232 S_per_cm2",
  747. erev="-81.5 mV",
  748. group_id="all_minus_myelin",
  749. ion="non_specific",
  750. ion_chan_def_file="channels/pas.channel.nml",
  751. )
  752. cell.set_resistivity("0.1 kohm_cm", group_id="all_minus_myelin")
  753. cell.set_specific_capacitance("1 uF_per_cm2", group_id="all_minus_myelin")
  754. cell.set_init_memb_potential("-80mV")
  755. # myelin
  756. cell.set_specific_capacitance("0.02 uF_per_cm2", group_id="myelin_group")
  757. cell.set_resistivity("0.1 kohm_cm", group_id="myelin_group")
  758. # 10mV is default for Neuron spike threshold in NetCon
  759. # https://www.neuron.yale.edu/neuron/static/py_doc/modelspec/programmatic/network/netcon.html
  760. cell.biophysical_properties.membrane_properties.spike_threshes.append(neuroml.SpikeThresh(value="10mV", segment_groups='all'))
  761. # write passive cell
  762. write_neuroml2_file(celldoc, f"{cellname}.pas.cell.nml")
  763. # somatic
  764. soma_group = cell.get_segment_group("soma_group")
  765. sgid = soma_group.id
  766. print(f"Adding channels to {sgid}")
  767. # Na
  768. cell.add_channel_density(
  769. nml_cell_doc=celldoc,
  770. cd_id="NaTg_somatic",
  771. ion_channel="NaTg_SST_somatic",
  772. cond_density="0.127 S_per_cm2",
  773. erev="50 mV",
  774. group_id=sgid,
  775. ion="na",
  776. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  777. )
  778. # hcn
  779. cell.add_channel_density(
  780. nml_cell_doc=celldoc,
  781. cd_id="Ih_somatic",
  782. ion_channel="Ih",
  783. cond_density="0.0000431 S_per_cm2",
  784. erev="-45 mV",
  785. group_id=sgid,
  786. ion="hcn",
  787. ion_chan_def_file="channels/Ih.channel.nml",
  788. )
  789. # K
  790. cell.add_channel_density(
  791. nml_cell_doc=celldoc,
  792. cd_id="K_P_somatic",
  793. ion_channel="K_P",
  794. cond_density="0.0111 S_per_cm2",
  795. erev="-85 mV",
  796. group_id=sgid,
  797. ion="k",
  798. ion_chan_def_file="channels/K_P.channel.nml",
  799. )
  800. cell.add_channel_density(
  801. nml_cell_doc=celldoc,
  802. cd_id="K_T_somatic",
  803. ion_channel="K_T",
  804. cond_density="0.00000 S_per_cm2",
  805. erev="-85 mV",
  806. group_id=sgid,
  807. ion="k",
  808. ion_chan_def_file="channels/K_T.channel.nml",
  809. )
  810. cell.add_channel_density(
  811. nml_cell_doc=celldoc,
  812. cd_id="Kv3_1_somatic",
  813. ion_channel="Kv3_1",
  814. cond_density="0.871 S_per_cm2",
  815. erev="-85 mV",
  816. group_id=sgid,
  817. ion="k",
  818. ion_chan_def_file="channels/Kv3_1.channel.nml",
  819. )
  820. cell.add_channel_density(
  821. nml_cell_doc=celldoc,
  822. cd_id="Im_somatic",
  823. ion_channel="Im",
  824. cond_density="0.000158 S_per_cm2",
  825. erev="-85 mV",
  826. group_id=sgid,
  827. ion="k",
  828. ion_chan_def_file="channels/Im.channel.nml",
  829. )
  830. cell.add_channel_density(
  831. nml_cell_doc=celldoc,
  832. cd_id="SK_somatic",
  833. ion_channel="SK",
  834. cond_density="0.00 S_per_cm2",
  835. erev="-85 mV",
  836. group_id=sgid,
  837. ion="k",
  838. ion_chan_def_file="channels/SK.channel.nml",
  839. )
  840. # Ca
  841. # external concentration is set to defaults that NEURON
  842. # starts with
  843. # internal concentration is set to minCai in mod file
  844. cell.add_intracellular_property(
  845. "Species",
  846. validate=False,
  847. id="ca",
  848. concentration_model="CaDynamics_E2_NML2_SST_somatic",
  849. ion="ca",
  850. initial_concentration="1e-4 mM",
  851. initial_ext_concentration="2.0E-6 mol_per_cm3",
  852. segment_groups=sgid,
  853. )
  854. # https://www.neuron.yale.edu/neuron/static/new_doc/modelspec/programmatic/ions.html
  855. cell.add_channel_density_v(
  856. "ChannelDensityNernst",
  857. nml_cell_doc=celldoc,
  858. id="Ca_HVA_somatic",
  859. ion_channel="Ca_HVA",
  860. cond_density="0.00355 S_per_cm2",
  861. segment_groups=sgid,
  862. ion="ca",
  863. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  864. )
  865. cell.add_channel_density_v(
  866. "ChannelDensityNernst",
  867. nml_cell_doc=celldoc,
  868. id="Ca_LVA_somatic",
  869. ion_channel="Ca_LVA",
  870. cond_density="0.00314 S_per_cm2",
  871. segment_groups=sgid,
  872. ion="ca",
  873. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  874. )
  875. # Basal
  876. basal_group = cell.get_segment_group("basal_dendrite_group")
  877. sgid = basal_group.id
  878. cell.set_specific_capacitance("1 uF_per_cm2", group_id=sgid)
  879. cell.add_channel_density(
  880. nml_cell_doc=celldoc,
  881. cd_id="Ih_basal",
  882. ion_channel="Ih",
  883. cond_density="0.0000949 S_per_cm2",
  884. erev="-45 mV",
  885. group_id=sgid,
  886. ion="hcn",
  887. ion_chan_def_file="channels/Ih.channel.nml",
  888. )
  889. # axonal
  890. sgs = cell.get_segment_group("axon_group")
  891. sgid = sgs.id
  892. print(f"Adding channels to {sgid}")
  893. # Na
  894. cell.add_channel_density(
  895. nml_cell_doc=celldoc,
  896. cd_id="NaTg_axonal",
  897. ion_channel="NaTg_SST_axonal",
  898. cond_density="0.343 S_per_cm2",
  899. erev="50 mV",
  900. group_id=sgid,
  901. ion="na",
  902. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  903. )
  904. cell.add_channel_density(
  905. nml_cell_doc=celldoc,
  906. cd_id="Nap_axonal",
  907. ion_channel="Nap",
  908. cond_density="0.000444 S_per_cm2",
  909. erev="50 mV",
  910. group_id=sgid,
  911. ion="na",
  912. ion_chan_def_file="channels/Nap.channel.nml",
  913. )
  914. # K
  915. cell.add_channel_density(
  916. nml_cell_doc=celldoc,
  917. cd_id="K_P_axonal",
  918. ion_channel="K_P",
  919. cond_density="0.0295 S_per_cm2",
  920. erev="-85 mV",
  921. group_id=sgid,
  922. ion="k",
  923. ion_chan_def_file="channels/K_P.channel.nml",
  924. )
  925. cell.add_channel_density(
  926. nml_cell_doc=celldoc,
  927. cd_id="K_T_axonal",
  928. ion_channel="K_T",
  929. cond_density="0.023 S_per_cm2",
  930. erev="-85 mV",
  931. group_id=sgid,
  932. ion="k",
  933. ion_chan_def_file="channels/K_T.channel.nml",
  934. )
  935. cell.add_channel_density(
  936. nml_cell_doc=celldoc,
  937. cd_id="Kv3_1_axonal",
  938. ion_channel="Kv3_1",
  939. cond_density="0.984 S_per_cm2",
  940. erev="-85 mV",
  941. group_id=sgid,
  942. ion="k",
  943. ion_chan_def_file="channels/Kv3_1.channel.nml",
  944. )
  945. cell.add_channel_density(
  946. nml_cell_doc=celldoc,
  947. cd_id="Im_axonal",
  948. ion_channel="Im",
  949. cond_density="0.000317 S_per_cm2",
  950. erev="-85 mV",
  951. group_id=sgid,
  952. ion="k",
  953. ion_chan_def_file="channels/Im.channel.nml",
  954. )
  955. cell.add_channel_density(
  956. nml_cell_doc=celldoc,
  957. cd_id="SK_axonal",
  958. ion_channel="SK",
  959. cond_density="0.00113 S_per_cm2",
  960. erev="-85 mV",
  961. group_id=sgid,
  962. ion="k",
  963. ion_chan_def_file="channels/SK.channel.nml",
  964. )
  965. # Ca
  966. cell.add_channel_density_v(
  967. "ChannelDensityNernst",
  968. nml_cell_doc=celldoc,
  969. id="Ca_HVA_axonal",
  970. ion_channel="Ca_HVA",
  971. cond_density="0.00145 S_per_cm2",
  972. segment_groups=sgid,
  973. ion="ca",
  974. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  975. )
  976. cell.add_channel_density_v(
  977. "ChannelDensityNernst",
  978. nml_cell_doc=celldoc,
  979. id="Ca_LVA_axonal",
  980. ion_channel="Ca_LVA",
  981. cond_density="0.0627 S_per_cm2",
  982. segment_groups=sgid,
  983. ion="ca",
  984. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  985. )
  986. # external concentration is set to defaults that NEURON
  987. # starts with
  988. # internal concentration is set to minCai in mod file
  989. cell.add_intracellular_property(
  990. "Species",
  991. validate=False,
  992. id="ca",
  993. concentration_model="CaDynamics_E2_NML2_SST_axonal",
  994. ion="ca",
  995. initial_concentration="1e-4 mM",
  996. initial_ext_concentration="2.0E-6 mol_per_cm3",
  997. segment_groups=sgid,
  998. )
  999. # HCN
  1000. cell.add_channel_density(
  1001. nml_cell_doc=celldoc,
  1002. cd_id="Ih_axonal",
  1003. ion_channel="Ih",
  1004. cond_density="0.00001 S_per_cm2",
  1005. erev="-45 mV",
  1006. group_id=sgid,
  1007. ion="hcn",
  1008. ion_chan_def_file="channels/Ih.channel.nml",
  1009. )
  1010. # L1 validation
  1011. cell.validate(recursive=True)
  1012. cell.summary(morph=True, biophys=True)
  1013. # use pynml writer to also run L2 validation
  1014. write_neuroml2_file(celldoc, f"{cellname}.cell.nml")
  1015. def postprocess_HL23VIP():
  1016. """Post process HL23VIP and add biophysics.
  1017. Each cell needs its biophysics to be added, so we do each cell separately.
  1018. """
  1019. cellname = "HL23VIP"
  1020. celldoc = load_and_setup_cell(cellname)
  1021. cell = celldoc.cells[0] # type: neuroml.Cell
  1022. print("Segment groups:")
  1023. for sg in cell.morphology.segment_groups:
  1024. print(f"** {sg.id} **")
  1025. print(cell.get_all_segments_in_group(sg.id))
  1026. print()
  1027. # biophysics
  1028. # include calcium dynamics component
  1029. celldoc.add(neuroml.IncludeType(href="CaDynamics_E2_NML2.nml"), validate=False)
  1030. # all
  1031. # Note: ion for passive channel must be "non_specific" for NEURON
  1032. cell.add_channel_density(
  1033. nml_cell_doc=celldoc,
  1034. cd_id="pas",
  1035. ion_channel="pas",
  1036. cond_density="2.5756438955642182e-05 S_per_cm2",
  1037. erev="-79.74132024971513 mV",
  1038. group_id="all",
  1039. ion="non_specific",
  1040. ion_chan_def_file="channels/pas.channel.nml",
  1041. )
  1042. cell.set_resistivity("0.1 kohm_cm", group_id="all")
  1043. cell.set_specific_capacitance("2 uF_per_cm2", group_id="all")
  1044. cell.set_init_memb_potential("-80mV")
  1045. # 10mV is default for Neuron spike threshold in NetCon
  1046. # https://www.neuron.yale.edu/neuron/static/py_doc/modelspec/programmatic/network/netcon.html
  1047. cell.biophysical_properties.membrane_properties.spike_threshes.append(neuroml.SpikeThresh(value="10mV", segment_groups='all'))
  1048. # write passive cell
  1049. write_neuroml2_file(celldoc, f"{cellname}.pas.cell.nml")
  1050. cell.add_channel_density(
  1051. nml_cell_doc=celldoc,
  1052. cd_id="Ih",
  1053. ion_channel="Ih",
  1054. cond_density="4.274951616063423e-05 S_per_cm2",
  1055. erev="-45 mV",
  1056. group_id="all",
  1057. ion="hcn",
  1058. ion_chan_def_file="channels/Ih.channel.nml",
  1059. )
  1060. # somatic
  1061. soma_group = cell.get_segment_group("soma_group")
  1062. sgid = soma_group.id
  1063. print(f"Adding channels to {sgid}")
  1064. # Na
  1065. cell.add_channel_density(
  1066. nml_cell_doc=celldoc,
  1067. cd_id="NaTg_somatic",
  1068. ion_channel="NaTg_VIP_somatic",
  1069. cond_density="0.11491205828369114 S_per_cm2",
  1070. erev="50 mV",
  1071. group_id=sgid,
  1072. ion="na",
  1073. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  1074. )
  1075. cell.add_channel_density(
  1076. nml_cell_doc=celldoc,
  1077. cd_id="Nap_somatic",
  1078. ion_channel="Nap",
  1079. cond_density="0.0001895305240694194 S_per_cm2",
  1080. erev="50 mV",
  1081. group_id=sgid,
  1082. ion="na",
  1083. ion_chan_def_file="channels/Nap.channel.nml",
  1084. )
  1085. # K
  1086. cell.add_channel_density(
  1087. nml_cell_doc=celldoc,
  1088. cd_id="K_P_somatic",
  1089. ion_channel="K_P",
  1090. cond_density="0.0009925418924114282 S_per_cm2",
  1091. erev="-85 mV",
  1092. group_id=sgid,
  1093. ion="k",
  1094. ion_chan_def_file="channels/K_P.channel.nml",
  1095. )
  1096. cell.add_channel_density(
  1097. nml_cell_doc=celldoc,
  1098. cd_id="K_T_somatic",
  1099. ion_channel="K_T",
  1100. cond_density="0.009051981253674193 S_per_cm2",
  1101. erev="-85 mV",
  1102. group_id=sgid,
  1103. ion="k",
  1104. ion_chan_def_file="channels/K_T.channel.nml",
  1105. )
  1106. cell.add_channel_density(
  1107. nml_cell_doc=celldoc,
  1108. cd_id="Kv3_1_somatic",
  1109. ion_channel="Kv3_1",
  1110. cond_density="0.31215653649208114 S_per_cm2",
  1111. erev="-85 mV",
  1112. group_id=sgid,
  1113. ion="k",
  1114. ion_chan_def_file="channels/Kv3_1.channel.nml",
  1115. )
  1116. cell.add_channel_density(
  1117. nml_cell_doc=celldoc,
  1118. cd_id="Im_somatic",
  1119. ion_channel="Im",
  1120. cond_density="0.0003679378262289559 S_per_cm2",
  1121. erev="-85 mV",
  1122. group_id=sgid,
  1123. ion="k",
  1124. ion_chan_def_file="channels/Im.channel.nml",
  1125. )
  1126. cell.add_channel_density(
  1127. nml_cell_doc=celldoc,
  1128. cd_id="SK_somatic",
  1129. ion_channel="SK",
  1130. cond_density="0.1655502166633749 S_per_cm2",
  1131. erev="-85 mV",
  1132. group_id=sgid,
  1133. ion="k",
  1134. ion_chan_def_file="channels/SK.channel.nml",
  1135. )
  1136. # Ca
  1137. # external concentration is set to defaults that NEURON
  1138. # starts with
  1139. # internal concentration is set to minCai in mod file
  1140. cell.add_intracellular_property(
  1141. "Species",
  1142. validate=False,
  1143. id="ca",
  1144. concentration_model="CaDynamics_E2_NML2_VIP_somatic",
  1145. ion="ca",
  1146. initial_concentration="1e-4 mM",
  1147. initial_ext_concentration="2.0E-6 mol_per_cm3",
  1148. segment_groups=sgid,
  1149. )
  1150. # https://www.neuron.yale.edu/neuron/static/new_doc/modelspec/programmatic/ions.html
  1151. cell.add_channel_density_v(
  1152. "ChannelDensityNernst",
  1153. nml_cell_doc=celldoc,
  1154. id="Ca_HVA_somatic",
  1155. ion_channel="Ca_HVA",
  1156. cond_density="4.384846294634834e-05 S_per_cm2",
  1157. segment_groups=sgid,
  1158. ion="ca",
  1159. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  1160. )
  1161. cell.add_channel_density_v(
  1162. "ChannelDensityNernst",
  1163. nml_cell_doc=celldoc,
  1164. id="Ca_LVA_somatic",
  1165. ion_channel="Ca_LVA",
  1166. cond_density="0.0034472458995879864 S_per_cm2",
  1167. segment_groups=sgid,
  1168. ion="ca",
  1169. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  1170. )
  1171. # axonal
  1172. sgs = cell.get_segment_group("axon_group")
  1173. sgid = sgs.id
  1174. print(f"Adding channels to {sgid}")
  1175. # Na
  1176. cell.add_channel_density(
  1177. nml_cell_doc=celldoc,
  1178. cd_id="NaTg_axonal",
  1179. ion_channel="NaTg_VIP_axonal",
  1180. cond_density="0.20112200814143477 S_per_cm2",
  1181. erev="50 mV",
  1182. group_id=sgid,
  1183. ion="na",
  1184. ion_chan_def_file="channels/NaTg/NaTg.channel.nml",
  1185. )
  1186. cell.add_channel_density(
  1187. nml_cell_doc=celldoc,
  1188. cd_id="Nap_axonal",
  1189. ion_channel="Nap",
  1190. cond_density="0.0006248906854665301 S_per_cm2",
  1191. erev="50 mV",
  1192. group_id=sgid,
  1193. ion="na",
  1194. ion_chan_def_file="channels/Nap.channel.nml",
  1195. )
  1196. # K
  1197. cell.add_channel_density(
  1198. nml_cell_doc=celldoc,
  1199. cd_id="K_P_axonal",
  1200. ion_channel="K_P",
  1201. cond_density="0.26489876414660096 S_per_cm2",
  1202. erev="-85 mV",
  1203. group_id=sgid,
  1204. ion="k",
  1205. ion_chan_def_file="channels/K_P.channel.nml",
  1206. )
  1207. cell.add_channel_density(
  1208. nml_cell_doc=celldoc,
  1209. cd_id="K_T_axonal",
  1210. ion_channel="K_T",
  1211. cond_density="0.014364427062274185 S_per_cm2",
  1212. erev="-85 mV",
  1213. group_id=sgid,
  1214. ion="k",
  1215. ion_chan_def_file="channels/K_T.channel.nml",
  1216. )
  1217. cell.add_channel_density(
  1218. nml_cell_doc=celldoc,
  1219. cd_id="Kv3_1_axonal",
  1220. ion_channel="Kv3_1",
  1221. cond_density="0.0011201608191112877 S_per_cm2",
  1222. erev="-85 mV",
  1223. group_id=sgid,
  1224. ion="k",
  1225. ion_chan_def_file="channels/Kv3_1.channel.nml",
  1226. )
  1227. cell.add_channel_density(
  1228. nml_cell_doc=celldoc,
  1229. cd_id="Im_axonal",
  1230. ion_channel="Im",
  1231. cond_density="0.00013891465461042372 S_per_cm2",
  1232. erev="-85 mV",
  1233. group_id=sgid,
  1234. ion="k",
  1235. ion_chan_def_file="channels/Im.channel.nml",
  1236. )
  1237. cell.add_channel_density(
  1238. nml_cell_doc=celldoc,
  1239. cd_id="SK_axonal",
  1240. ion_channel="SK",
  1241. cond_density="0.7027792087501376 S_per_cm2",
  1242. erev="-85 mV",
  1243. group_id=sgid,
  1244. ion="k",
  1245. ion_chan_def_file="channels/SK.channel.nml",
  1246. )
  1247. # Ca
  1248. cell.add_channel_density_v(
  1249. "ChannelDensityNernst",
  1250. nml_cell_doc=celldoc,
  1251. id="Ca_HVA_axonal",
  1252. ion_channel="Ca_HVA",
  1253. cond_density="2.819397237794038e-05 S_per_cm2",
  1254. segment_groups=sgid,
  1255. ion="ca",
  1256. ion_chan_def_file="channels/Ca_HVA.channel.nml",
  1257. )
  1258. cell.add_channel_density_v(
  1259. "ChannelDensityNernst",
  1260. nml_cell_doc=celldoc,
  1261. id="Ca_LVA_axonal",
  1262. ion_channel="Ca_LVA",
  1263. cond_density="0.010354001513952075 S_per_cm2",
  1264. segment_groups=sgid,
  1265. ion="ca",
  1266. ion_chan_def_file="channels/Ca_LVA.channel.nml",
  1267. )
  1268. # external concentration is set to defaults that NEURON
  1269. # starts with
  1270. # internal concentration is set to minCai in mod file
  1271. cell.add_intracellular_property(
  1272. "Species",
  1273. validate=False,
  1274. id="ca",
  1275. concentration_model="CaDynamics_E2_NML2_VIP_axonal",
  1276. ion="ca",
  1277. initial_concentration="1e-4 mM",
  1278. initial_ext_concentration="2.0E-6 mol_per_cm3",
  1279. segment_groups=sgid,
  1280. )
  1281. # L1 validation
  1282. cell.validate(recursive=True)
  1283. cell.summary(morph=True, biophys=True)
  1284. # use pynml writer to also run L2 validation
  1285. write_neuroml2_file(celldoc, f"{cellname}.cell.nml")
  1286. def analyse_HL23PYR(hyperpolarising: bool = True, depolarising: bool = True):
  1287. """Generate various curves for HL23PYR cells
  1288. :returns: None
  1289. """
  1290. cellname = "HL23PYR"
  1291. if hyperpolarising:
  1292. # hyper-polarising inputs
  1293. generate_current_vs_frequency_curve(
  1294. nml2_file=f"{cellname}.cell.nml",
  1295. cell_id=cellname,
  1296. custom_amps_nA=list(numpy.arange(-0.05, -0.1, -0.01)),
  1297. temperature="34 degC",
  1298. pre_zero_pulse=200,
  1299. post_zero_pulse=300,
  1300. plot_voltage_traces=True,
  1301. plot_iv=True,
  1302. plot_if=False,
  1303. simulator="jNeuroML_NEURON",
  1304. analysis_delay=300.0,
  1305. analysis_duration=400.0,
  1306. )
  1307. if depolarising:
  1308. # depolarising inputs
  1309. generate_current_vs_frequency_curve(
  1310. nml2_file=f"{cellname}.cell.nml",
  1311. cell_id=cellname,
  1312. plot_voltage_traces=True,
  1313. spike_threshold_mV=-10.0,
  1314. # custom_amps_nA=list(numpy.arange(0, 0.3, 0.05)),
  1315. custom_amps_nA=[0.2],
  1316. temperature="34 degC",
  1317. pre_zero_pulse=200,
  1318. post_zero_pulse=300,
  1319. plot_iv=True,
  1320. simulator="jNeuroML_NEURON",
  1321. analysis_delay=50.0,
  1322. analysis_duration=200.0,
  1323. )
  1324. def analyse_HL23PV(hyperpolarising: bool = True, depolarising: bool = True):
  1325. """Generate various curves for HL23PV cells
  1326. :returns: None
  1327. """
  1328. cellname = "HL23PV"
  1329. if hyperpolarising:
  1330. # hyper-polarising inputs
  1331. generate_current_vs_frequency_curve(
  1332. nml2_file=f"{cellname}.cell.nml",
  1333. cell_id=cellname,
  1334. custom_amps_nA=list(numpy.arange(-0.05, -0.1, -0.01)),
  1335. pre_zero_pulse=200,
  1336. post_zero_pulse=300,
  1337. plot_voltage_traces=True,
  1338. plot_iv=True,
  1339. plot_if=False,
  1340. simulator="jNeuroML_NEURON",
  1341. analysis_delay=300.0,
  1342. analysis_duration=400.0,
  1343. )
  1344. if depolarising:
  1345. # depolarising inputs
  1346. generate_current_vs_frequency_curve(
  1347. nml2_file=f"{cellname}.cell.nml",
  1348. cell_id=cellname,
  1349. plot_voltage_traces=True,
  1350. spike_threshold_mV=-10.0,
  1351. custom_amps_nA=list(numpy.arange(0, 0.3, 0.01)),
  1352. pre_zero_pulse=200,
  1353. post_zero_pulse=300,
  1354. plot_iv=True,
  1355. simulator="jNeuroML_NEURON",
  1356. analysis_delay=300.0,
  1357. analysis_duration=400.0,
  1358. )
  1359. def analyse_HL23SST(hyperpolarising: bool = True, depolarising: bool = True):
  1360. """Generate various curves for HL23SST cells
  1361. :returns: None
  1362. """
  1363. cellname = "HL23SST"
  1364. if hyperpolarising:
  1365. # hyper-polarising inputs
  1366. generate_current_vs_frequency_curve(
  1367. nml2_file=f"{cellname}.cell.nml",
  1368. cell_id=cellname,
  1369. custom_amps_nA=list(numpy.arange(-0.05, -0.1, -0.01)),
  1370. pre_zero_pulse=200,
  1371. post_zero_pulse=300,
  1372. plot_voltage_traces=True,
  1373. plot_iv=True,
  1374. plot_if=False,
  1375. simulator="jNeuroML_NEURON",
  1376. analysis_delay=300.0,
  1377. analysis_duration=400.0,
  1378. )
  1379. if depolarising:
  1380. # depolarising inputs
  1381. generate_current_vs_frequency_curve(
  1382. nml2_file=f"{cellname}.cell.nml",
  1383. cell_id=cellname,
  1384. plot_voltage_traces=True,
  1385. spike_threshold_mV=-10.0,
  1386. # custom_amps_nA=list(numpy.arange(0, 0.3, 0.01)),
  1387. custom_amps_nA=[0.2],
  1388. pre_zero_pulse=200,
  1389. post_zero_pulse=300,
  1390. plot_iv=True,
  1391. simulator="jNeuroML_NEURON",
  1392. analysis_delay=300.0,
  1393. analysis_duration=400.0,
  1394. )
  1395. def analyse_HL23VIP(hyperpolarising: bool = True, depolarising: bool = True):
  1396. """Generate various curves for HL23VIP cells
  1397. :returns: None
  1398. """
  1399. cellname = "HL23VIP"
  1400. if hyperpolarising:
  1401. # hyper-polarising inputs
  1402. generate_current_vs_frequency_curve(
  1403. nml2_file=f"{cellname}.cell.nml",
  1404. cell_id=cellname,
  1405. custom_amps_nA=list(numpy.arange(-0.05, -0.1, -0.01)),
  1406. pre_zero_pulse=200,
  1407. post_zero_pulse=300,
  1408. plot_voltage_traces=True,
  1409. plot_iv=True,
  1410. plot_if=False,
  1411. simulator="jNeuroML_NEURON",
  1412. analysis_delay=300.0,
  1413. analysis_duration=400.0,
  1414. )
  1415. if depolarising:
  1416. # depolarising inputs
  1417. generate_current_vs_frequency_curve(
  1418. nml2_file=f"{cellname}.cell.nml",
  1419. cell_id=cellname,
  1420. plot_voltage_traces=True,
  1421. spike_threshold_mV=-10.0,
  1422. # custom_amps_nA=list(numpy.arange(0, 0.3, 0.01)),
  1423. custom_amps_nA=[0.2],
  1424. pre_zero_pulse=200,
  1425. post_zero_pulse=300,
  1426. plot_iv=True,
  1427. simulator="jNeuroML_NEURON",
  1428. analysis_delay=300.0,
  1429. analysis_duration=400.0,
  1430. )
  1431. def simulate_test_network(cells: list = []):
  1432. """Create and simulate a test network
  1433. WIP: does not simulate it yet.
  1434. :param cells: list of cell names to simulate
  1435. :type cells: list of strings
  1436. :returns: None
  1437. """
  1438. net_doc = neuroml.NeuroMLDocument.component_factory("NeuroMLDocument", id="HL23")
  1439. network = net_doc.add(
  1440. "Network",
  1441. id="HL23Net",
  1442. type="networkWithTemperature",
  1443. temperature="34 degC",
  1444. validate=False,
  1445. ) # type: neuroml.Network
  1446. for cell in cells:
  1447. # a document for the cell with input for OMV test
  1448. cell_net_doc = neuroml.NeuroMLDocument.component_factory(
  1449. "NeuroMLDocument", id=f"{cell}"
  1450. )
  1451. cell_network = cell_net_doc.add(
  1452. "Network",
  1453. id=f"{cell}Net",
  1454. type="networkWithTemperature",
  1455. temperature="34 degC",
  1456. validate=False,
  1457. ) # type: neuroml.Network
  1458. cell_net_doc.add("IncludeType", href=f"{cell}.cell.nml")
  1459. cell_pop = cell_network.add(
  1460. "Population",
  1461. id=f"{cell}_pop",
  1462. type="populationList",
  1463. component=f"{cell}",
  1464. validate=False,
  1465. ) # type: neuroml.Population
  1466. cell_pop.add(
  1467. "Property",
  1468. tag="color",
  1469. value=f"{random.random()} {random.random()} {random.random()}",
  1470. )
  1471. cell_pop.add("Property", tag="region", value="L23")
  1472. cell_pop.add(
  1473. "Instance",
  1474. id="0",
  1475. location=cell_pop.component_factory(
  1476. "Location",
  1477. x="0",
  1478. y="0",
  1479. z="0",
  1480. ),
  1481. )
  1482. # to match the test_*hoc NEURON files
  1483. cell_net_doc.add(
  1484. "PulseGenerator",
  1485. id=f"pg_{cell}",
  1486. notes="Simple pulse generator",
  1487. delay="50ms",
  1488. duration="200ms",
  1489. amplitude="0.2nA",
  1490. )
  1491. cell_inputs = cell_network.add(
  1492. "InputList",
  1493. id=f"stim_iclamp_{cell}",
  1494. populations=f"{cell}_pop",
  1495. component=f"pg_{cell}",
  1496. validate=False,
  1497. )
  1498. cell_inputs.add(
  1499. "Input", id=0, target=f"../{cell}_pop/0", destination="synapses"
  1500. )
  1501. cell_net_doc.validate(True)
  1502. write_neuroml2_file(cell_net_doc, f"{cell}.net.nml")
  1503. cell_net_sim = LEMSSimulation(
  1504. f"{cell}_sim", duration=300.0, dt=0.01, target=cell_network.id
  1505. )
  1506. cell_net_sim.include_neuroml2_file(f"{cell}.net.nml")
  1507. cell_net_sim.create_output_file(
  1508. id=f"{cell}_net_output", file_name=f"{cell}_net.dat"
  1509. )
  1510. cell_net_sim.add_column_to_output_file(
  1511. output_file_id=f"{cell}_net_output",
  1512. column_id=f"{cell}_pop_0_v",
  1513. quantity=f"{cell}_pop/0/{cell}/0/v",
  1514. )
  1515. # Save LEMS simulation to file
  1516. cell_sim_file = cell_net_sim.save_to_file()
  1517. # Run the simulation using the NEURON simulator
  1518. run_lems_with_jneuroml_neuron(
  1519. cell_sim_file, max_memory="8G", nogui=True, plot=False, skip_run=False
  1520. )
  1521. # network with all 4 cells
  1522. net_doc.add("IncludeType", href=f"{cell}.cell.nml")
  1523. pop = network.add(
  1524. "Population",
  1525. id=f"{cell}_pop",
  1526. type="populationList",
  1527. component=f"{cell}",
  1528. validate=False,
  1529. ) # type: neuroml.Population
  1530. pop.add(
  1531. "Property",
  1532. tag="color",
  1533. value=f"{random.random()} {random.random()} {random.random()}",
  1534. )
  1535. pop.add("Property", tag="region", value="L23")
  1536. pop.add(
  1537. "Instance",
  1538. id="0",
  1539. location=pop.component_factory(
  1540. "Location",
  1541. x=f"{random.randint(0, 200)}",
  1542. y=f"{random.randint(0, 200)}",
  1543. z=f"{random.randint(0, 200)}",
  1544. ),
  1545. )
  1546. net_doc.add(
  1547. "PulseGenerator",
  1548. id=f"pg_{cell}",
  1549. notes="Simple pulse generator",
  1550. delay="50ms",
  1551. duration="200ms",
  1552. amplitude="0.2nA",
  1553. )
  1554. network.add("ExplicitInput", target="pop0[0]", input=f"pg_{cell}")
  1555. net_doc.validate(True)
  1556. write_neuroml2_file(net_doc, "HL23.net.nml")
  1557. # plot_2D("HL23.net.nml", plane2d="xy")
  1558. if __name__ == "__main__":
  1559. cellnames = ["HL23PV", "HL23PYR", "HL23SST", "HL23VIP"]
  1560. if "-postprocall" in sys.argv:
  1561. postprocess_HL23VIP()
  1562. postprocess_HL23PV()
  1563. postprocess_HL23PYR()
  1564. postprocess_HL23SST()
  1565. """
  1566. postprocess_HL23VIP()
  1567. analyse_HL23VIP(True, True)
  1568. simulate_test_network(cellnames)
  1569. postprocess_HL23PV()
  1570. analyse_HL23PV(True, True)
  1571. postprocess_HL23PYR()
  1572. analyse_HL23PYR(False, True)
  1573. analyse_HL23SST(True, True)
  1574. """
  1575. postprocess_HL23SST()