|
| 1 | +/* |
| 2 | +{%- if banner %} |
| 3 | +{{banner}} |
| 4 | +{%- endif %} |
| 5 | +*/ |
| 6 | +{load_file("stdrun.hoc")} |
| 7 | +{load_file("import3d.hoc")} |
| 8 | + |
| 9 | +{%- if global_params %} |
| 10 | +/* |
| 11 | + * Check that global parameters are the same as with the optimization |
| 12 | + */ |
| 13 | +proc check_parameter(/* name, expected_value, value */){ |
| 14 | + strdef error |
| 15 | + if($2 != $3){ |
| 16 | + sprint(error, "Parameter %s has different value %f != %f", $s1, $2, $3) |
| 17 | + execerror(error) |
| 18 | + } |
| 19 | +} |
| 20 | +proc check_simulator() { |
| 21 | + {%- for param, value in global_params.items() %} |
| 22 | + check_parameter("{{param}}", {{value}}, {{param}}) |
| 23 | + {%- endfor %} |
| 24 | +} |
| 25 | +{%- endif %} |
| 26 | +{%- if ignored_global_params %} |
| 27 | +/* The following global parameters were set in BluePyOpt |
| 28 | +{%- for param, value in ignored_global_params.items() %} |
| 29 | + * {{param}} = {{value}} |
| 30 | +{%- endfor %} |
| 31 | + */ |
| 32 | +{%- endif %} |
| 33 | + |
| 34 | +begintemplate {{template_name}} |
| 35 | + public init, morphology, geom_nseg_fixed, geom_nsec, getCell, getCCell, setCCell, gid, getCell |
| 36 | + public channel_seed, channel_seed_set |
| 37 | + public connect2target, clear, ASCIIrpt |
| 38 | + public soma, dend, apic, axon, myelin, getThreshold |
| 39 | + create soma[1], dend[1], apic[1], axon[1], myelin[1] |
| 40 | + public nSecAll, nSecSoma, nSecApical, nSecBasal, nSecMyelinated, nSecAxonalOrig, nSecAxonal |
| 41 | + public CellRef, synHelperList, synlist |
| 42 | + objref this, CellRef, segCounts, ASCIIrpt, synHelperList, synlist |
| 43 | + |
| 44 | + public all, somatic, apical, axonal, basal, myelinated, APC |
| 45 | + objref all, somatic, apical, axonal, basal, myelinated, APC |
| 46 | + |
| 47 | + |
| 48 | +obfunc getCell(){ |
| 49 | + return this |
| 50 | +} |
| 51 | + |
| 52 | +obfunc getCCell(){ |
| 53 | + return CellRef |
| 54 | +} |
| 55 | +proc setCCell(){ |
| 56 | + CellRef = $o1 |
| 57 | +} |
| 58 | + |
| 59 | +//----------------------------------------------------------------------------------------------- |
| 60 | + |
| 61 | +/*! |
| 62 | + * When clearing the model, the circular reference between Cells and CCells must be broken so the |
| 63 | + * entity watching reference counts can work. |
| 64 | + */ |
| 65 | +proc clear() { localobj nil |
| 66 | + CellRef = nil |
| 67 | +} |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +/*! |
| 72 | + * @param $o1 NetCon source (can be nil) |
| 73 | + * @param $o2 Variable where generated NetCon will be placed |
| 74 | + */ |
| 75 | +proc connect2target() { //$o1 target point process, $o2 returned NetCon |
| 76 | + soma $o2 = new NetCon(&v(1), $o1) |
| 77 | + $o2.threshold = -30 |
| 78 | +} |
| 79 | + |
| 80 | + |
| 81 | +proc init(/* args: morphology_dir, morphology_name */) { |
| 82 | + all = new SectionList() |
| 83 | + apical = new SectionList() |
| 84 | + axonal = new SectionList() |
| 85 | + basal = new SectionList() |
| 86 | + somatic = new SectionList() |
| 87 | + myelinated = new SectionList() |
| 88 | + |
| 89 | + synHelperList = new List() |
| 90 | + synlist = new List() |
| 91 | + |
| 92 | + //For compatibility with BBP CCells |
| 93 | + CellRef = this |
| 94 | + |
| 95 | + forall delete_section() |
| 96 | + |
| 97 | + gid = $1 |
| 98 | + |
| 99 | + if(numarg() >= 3) { |
| 100 | + load_morphology($s2, $s3) |
| 101 | + } else { |
| 102 | + {%- if morphology %} |
| 103 | + load_morphology($s2, "{{morphology}}") |
| 104 | + {%- else %} |
| 105 | + execerror("Template {{template_name}} requires morphology name to instantiate") |
| 106 | + {%- endif %} |
| 107 | + } |
| 108 | + |
| 109 | + geom_nseg() |
| 110 | + indexSections() |
| 111 | + {%- if replace_axon %} |
| 112 | + replace_axon() |
| 113 | + {%- endif %} |
| 114 | + insertChannel() |
| 115 | + biophys() |
| 116 | + |
| 117 | + // Initialize channel_seed_set to avoid accidents |
| 118 | + channel_seed_set = 0 |
| 119 | + // Initialize random number generators |
| 120 | + re_init_rng() |
| 121 | +} |
| 122 | + |
| 123 | +/*! |
| 124 | + * Assign section indices to the section voltage value. This will be useful later for serializing |
| 125 | + * the sections into an array. Note, that once the simulation begins, the voltage values will revert to actual data again. |
| 126 | + * |
| 127 | + * @param $o1 Import3d_GUI object |
| 128 | + */ |
| 129 | +proc indexSections() { local index |
| 130 | + index = 0 |
| 131 | + forsec all { |
| 132 | + v(0.0001) = index |
| 133 | + index = index +1 |
| 134 | + } |
| 135 | +} |
| 136 | + |
| 137 | +func getThreshold() { return 0.0 } |
| 138 | + |
| 139 | +proc load_morphology(/* morphology_dir, morphology_name */) {localobj morph, import, sf, extension, commands, pyobj |
| 140 | + strdef morph_path |
| 141 | + sprint(morph_path, "%s/%s", $s1, $s2) sf = new StringFunctions() |
| 142 | + extension = new String() sscanf(morph_path, "%s", extension.s) |
| 143 | + |
| 144 | + // TODO fix the `-3` here. |
| 145 | + sf.right(extension.s, sf.len(extension.s)-3) |
| 146 | + |
| 147 | + if( strcmp(extension.s, ".asc") == 0 ) { |
| 148 | + morph = new Import3d_Neurolucida3() |
| 149 | + } else if( strcmp(extension.s, ".swc" ) == 0) { |
| 150 | + morph = new Import3d_SWC_read() |
| 151 | + } else if( strcmp(extension.s, ".h5") == 0 ) { |
| 152 | + if(nrnpython ("from morphio_wrapper import MorphIOWrapper") == 1) { |
| 153 | + pyobj = new PythonObject() |
| 154 | + commands = pyobj.MorphIOWrapper(morph_path).morph_as_hoc() |
| 155 | + for i = 0, pyobj.len(commands) - 1 { |
| 156 | + execute(commands._[i], this) |
| 157 | + } |
| 158 | + indexSections() |
| 159 | + geom_nsec() |
| 160 | + } else { |
| 161 | + printf( ".h5 morphlogy used but cannot load 'morphio_wrapper'." ) |
| 162 | + quit() |
| 163 | + } |
| 164 | + } else { |
| 165 | + printf(extension.s) |
| 166 | + printf("Unsupported file format: Morphology file has to end with .asc, .swc or .h5" ) |
| 167 | + quit() |
| 168 | + } |
| 169 | +} |
| 170 | + |
| 171 | +/* |
| 172 | + * Assignment of mechanism values based on distance from the soma |
| 173 | + * Matches the BluePyOpt method |
| 174 | + */ |
| 175 | +proc distribute_distance(){local x localobj sl |
| 176 | + strdef stmp, distfunc, mech |
| 177 | + |
| 178 | + sl = $o1 |
| 179 | + mech = $s2 |
| 180 | + distfunc = $s3 |
| 181 | + this.soma[0] distance(0, 0.5) |
| 182 | + sprint(distfunc, "%%s %s(%%f) = %s", mech, distfunc) |
| 183 | + forsec sl for(x, 0) { |
| 184 | + sprint(stmp, distfunc, secname(), x, distance(x)) |
| 185 | + execute(stmp) |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +proc geom_nseg() { |
| 190 | + this.geom_nsec() //To count all sections |
| 191 | + //TODO: geom_nseg_fixed depends on segCounts which is calculated by |
| 192 | + // geom_nsec. Can this be collapsed? |
| 193 | + this.geom_nseg_fixed(40) |
| 194 | + this.geom_nsec() //To count all sections |
| 195 | +} |
| 196 | + |
| 197 | +proc insertChannel() { |
| 198 | + {%- for location, names in channels.items() %} |
| 199 | + forsec this.{{location}} { |
| 200 | + {%- for channel in names %} |
| 201 | + insert {{channel}} |
| 202 | + {%- endfor %} |
| 203 | + } |
| 204 | + {%- endfor %} |
| 205 | +} |
| 206 | + |
| 207 | +proc biophys() { |
| 208 | + {% for loc, parameters in section_params %} |
| 209 | + forsec CellRef.{{ loc }} { |
| 210 | + {%- for param in parameters %} |
| 211 | + {{ param.name }} = {{ param.value }} |
| 212 | + {%- endfor %} |
| 213 | + } |
| 214 | + {% endfor %} |
| 215 | + {%- for location, param_name, value in range_params %} |
| 216 | + distribute_distance(CellRef.{{location}}, "{{param_name}}", "{{value}}") |
| 217 | + {%- endfor %} |
| 218 | +} |
| 219 | + |
| 220 | +func sec_count(/* SectionList */) { local nSec |
| 221 | + nSec = 0 |
| 222 | + forsec $o1 { |
| 223 | + nSec += 1 |
| 224 | + } |
| 225 | + return nSec |
| 226 | +} |
| 227 | + |
| 228 | +/* |
| 229 | + * Iterate over the section and compute how many segments should be allocate to |
| 230 | + * each. |
| 231 | + */ |
| 232 | +proc geom_nseg_fixed(/* chunkSize */) { local secIndex, chunkSize |
| 233 | + chunkSize = $1 |
| 234 | + soma area(.5) // make sure diam reflects 3d points |
| 235 | + secIndex = 0 |
| 236 | + forsec all { |
| 237 | + nseg = 1 + 2*int(L/chunkSize) |
| 238 | + segCounts.x[secIndex] = nseg |
| 239 | + secIndex += 1 |
| 240 | + } |
| 241 | +} |
| 242 | + |
| 243 | +/* |
| 244 | + * Count up the number of sections |
| 245 | + */ |
| 246 | +proc geom_nsec() { local nSec |
| 247 | + nSecAll = sec_count(all) |
| 248 | + nSecSoma = sec_count(somatic) |
| 249 | + nSecApical = sec_count(apical) |
| 250 | + nSecBasal = sec_count(basal) |
| 251 | + nSecMyelinated = sec_count(myelinated) |
| 252 | + nSecAxonalOrig = nSecAxonal = sec_count(axonal) |
| 253 | + |
| 254 | + segCounts = new Vector() |
| 255 | + segCounts.resize(nSecAll) |
| 256 | + nSec = 0 |
| 257 | + forsec all { |
| 258 | + segCounts.x[nSec] = nseg |
| 259 | + nSec += 1 |
| 260 | + } |
| 261 | +} |
| 262 | + |
| 263 | +/* |
| 264 | + * Replace the axon built from the original morphology file with a stub axon |
| 265 | + */ |
| 266 | +{%- if replace_axon %} |
| 267 | + {{replace_axon}} |
| 268 | +{%- endif %} |
| 269 | + |
| 270 | + |
| 271 | +{{re_init_rng}} |
| 272 | + |
| 273 | +endtemplate {{template_name}} |
| 274 | + |
0 commit comments