46 DefineVar(
"len", &
len );
47 DefineVar(
"dia", &
dia );
48 DefineVar(
"maxP", &
maxP );
49 DefineVar(
"maxG", &
maxG );
50 DefineVar(
"maxL", &
maxL );
54 DefineVar(
"oldVal", &
oldVal );
56 if ( expr.find(
"oldVal" ) != string::npos )
66 static double H(
double arg )
71 double eval( vector< double >::const_iterator arg0 )
112 "Membrane resistivity, in ohm.m^2. Default value is 1.0.",
117 "Axial resistivity of cytoplasm, in ohm.m. Default value is 1.0.",
122 "Membrane Capacitance, in F/m^2. Default value is 0.01",
127 "Resting membrane potential of compartments, in Volts. "
128 "Default value is -0.065.",
133 "Angle to rotate cell geometry, around long axis of neuron. "
134 "Think Longitude. Units are radians. "
135 "Default value is zero, which means no rotation. ",
140 "Angle to rotate cell geometry, around elevation of neuron. "
141 "Think Latitude. Units are radians. "
142 "Default value is zero, which means no rotation. ",
148 "Name of source file from which to load a model. "
149 "Accepts swc and dotp formats at present. "
150 "Both these formats require that the appropriate channel "
151 "definitions should have been loaded into /library. ",
157 "compartmentLengthInLambdas",
158 "Units: meters (SI). \n"
159 "Electrotonic length to use for the largest compartment in the "
160 "model. Used to define subdivision of branches into compartments. "
161 "For example, if we set *compartmentLengthInLambdas* to 0.1, "
162 "and *lambda* (electrotonic length) is 250 microns, then it "
163 "sets the compartment length to 25 microns. Thus a dendritic "
164 "branch of 500 microns is subdivided into 20 commpartments. "
165 "If the branch is shorter than *compartmentLengthInLambdas*, "
166 "then it is not subdivided. "
167 "If *compartmentLengthInLambdas* is set to 0 then the original "
168 "compartmental structure of the model is preserved. "
169 " Note that this routine does NOT merge branches, even if "
170 "*compartmentLengthInLambdas* is bigger than the branch. "
171 "While all this subdivision is being done, the Neuron class "
172 "preserves as detailed a geometry as it can, so it can rebuild "
173 "the more detailed version if needed. "
174 "Default value of *compartmentLengthInLambdas* is 0. ",
181 "channelDistribution",
182 "Specification for distribution of channels, CaConcens and "
183 "any other model components that are defined as prototypes and "
184 "have to be placed on the electrical compartments.\n"
185 "Arguments: proto path field expr [field expr]...\n"
186 " Each entry is terminated with an empty string. "
187 "The prototype is any object created in */library*, "
188 "If a channel matching the prototype name already exists, then "
189 "all subsequent operations are applied to the extant channel and "
190 "a new one is not created. "
191 "The paired arguments are as follows: \n"
192 "The *field* argument specifies the name of the parameter "
193 "that is to be assigned by the expression.\n"
194 "The *expression* argument is a mathematical expression in "
195 "the muparser framework, which permits most operations including "
196 "trig and transcendental ones. Of course it also handles simple "
197 "numerical values like 1.0, 1e-10 and so on. "
198 "Available arguments for muParser are:\n"
199 " p, g, L, len, dia, maxP, maxG, maxL \n"
200 " p: path distance from soma, measured along dendrite, in metres.\n"
201 " g: geometrical distance from soma, in metres.\n"
202 " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n"
203 " len: length of compartment, in metres.\n"
204 " dia: for diameter of compartment, in metres.\n"
205 " maxP: Maximum value of *p* for this neuron. \n"
206 " maxG: Maximum value of *g* for this neuron. \n"
207 " maxL: Maximum value of *L* for this neuron.\n"
208 "The expression for the first field must evaluate to > 0 "
209 "for the channel to be installed. For example, for "
210 "channels, if Field == Gbar, and func( r, L, len, dia) < 0, \n"
211 "then the channel is not installed. This feature is typically "
212 "used with the sign() or Heaviside H() function to limit range: "
213 "for example: H(1 - L) will only put channels closer than "
214 "one length constant from the soma, and zero elsewhere. \n"
215 "Available fields are: \n"
216 "Channels: Gbar (install), Ek \n"
217 "CaConcen: shellDia (install), shellFrac (install), tau, min\n"
218 "Unless otherwise noted, all fields are scaled appropriately by "
219 "the dimensions of their compartment. Thus the channel "
220 "maximal conductance Gbar is automatically scaled by the area "
221 "of the compartment, and the user does not need to insert this "
222 "scaling into the calculations.\n"
223 "All parameters are expressed in SI units. Conductance, for "
224 "example, is Siemens/sq metre. "
226 "Some example function forms might be for a channel Gbar: \n"
227 " p < 10e-6 ? 400 : 0.0 \n"
229 " H(10e-6 - p) * 400 \n"
231 " ( sign(10e-6 - p) + 1) * 200 \n"
232 "Each of these forms instruct the function to "
233 "set channel Gbar to 400 S/m^2 only within 10 microns path "
236 " L < 1.0 ? 100 * exp( -L ) : 0.0 \n"
237 " ->Set channel Gbar to an exponentially falling function of "
238 "electrotonic distance from soma, provided L is under "
246 "passiveDistribution",
247 "Specification for distribution of passive properties of cell.\n"
248 "Arguments: . path field expr [field expr]...\n"
249 "Note that the arguments list starts with a period. "
250 " Each entry is terminated with an empty string. "
251 "The paired arguments are as follows: \n"
252 "The *field* argument specifies the name of the parameter "
253 "that is to be assigned by the expression.\n"
254 "The *expression* argument is a mathematical expression in "
255 "the muparser framework, which permits most operations including "
256 "trig and transcendental ones. Of course it also handles simple "
257 "numerical values like 1.0, 1e-10 and so on. "
258 "Available arguments for muParser are:\n"
259 " p, g, L, len, dia, maxP, maxG, maxL \n"
260 " p: path distance from soma, measured along dendrite, in metres.\n"
261 " g: geometrical distance from soma, in metres.\n"
262 " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n"
263 " len: length of compartment, in metres.\n"
264 " dia: for diameter of compartment, in metres.\n"
265 " maxP: Maximum value of *p* for this neuron. \n"
266 " maxG: Maximum value of *g* for this neuron. \n"
267 " maxL: Maximum value of *L* for this neuron.\n"
268 "Available fields are: \n"
269 "RM, RA, CM, Rm, Ra, Cm, Em, initVm \n"
270 "The first three fields are scaled appropriately by "
271 "the dimensions of their compartment. Thus the membrane "
272 "resistivity RM (ohms.m^2) is automatically scaled by the area "
273 "of the compartment, and the user does not need to insert this "
274 "scaling into the calculations to compute Rm."
275 "Using the Rm field lets the user directly assign the "
276 "membrane resistance (in ohms), presumably using len and dia.\n"
277 "Similarly, RA (ohms.m) and CM (Farads/m^2) are specific units "
278 "and the actual values for each compartment are assigned by "
279 "scaling by length and diameter. Ra (ohms) and Cm (Farads) "
280 "require explicit evaluation of the expression. "
281 "All parameters are expressed in SI units. Conductance, for "
282 "example, is Siemens/sq metre.\n"
283 "Note that time these calculations do NOT currently include spines\n",
290 "Specification for distribution of spines on dendrite. \n"
291 "Arguments: proto path spacing expr [field expr]...\n"
292 " Each entry is terminated with an empty string. "
293 "The *prototype* is any spine object created in */library*, \n"
294 "The *path* is the wildcard path of compartments on which to "
296 "The *spacing* is the spacing of spines, in metres. \n"
297 "The *expression* argument is a mathematical expression in "
298 "the muparser framework, which permits most operations including "
299 "trig and transcendental ones. Of course it also handles simple "
300 "numerical values like 1.0, 1e-10 and so on. "
301 "The paired arguments are as follows: \n"
302 "The *field* argument specifies the name of the parameter "
303 "that is to be assigned by the expression.\n"
304 "The *expression* argument is a mathematical expression as above. "
305 "Available arguments for muParser are:\n"
306 " p, g, L, len, dia, maxP, maxG, maxL \n"
307 " p: path distance from soma, measured along dendrite, in metres.\n"
308 " g: geometrical distance from soma, in metres.\n"
309 " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n"
310 " len: length of compartment, in metres.\n"
311 " dia: for diameter of compartment, in metres.\n"
312 " maxP: Maximum value of *p* for this neuron. \n"
313 " maxG: Maximum value of *g* for this neuron. \n"
314 " maxL: Maximum value of *L* for this neuron.\n"
315 "The expression for the *spacing* field must evaluate to > 0 for "
316 "the spine to be installed. For example, if the expresssion is\n"
318 "then the systemwill only put spines closer than "
319 "one length constant from the soma, and zero elsewhere. \n"
320 "Available spine parameters are: \n"
321 "spacing, minSpacing, size, sizeDistrib "
322 "angle, angleDistrib \n",
330 "Number of electrical compartments in model. ",
336 "Number of dendritic spines in model. ",
342 "Number of branches in dendrites. ",
347 "pathDistanceFromSoma",
348 "geometrical path distance of each segment from soma, measured by "
349 "threading along the dendrite.",
354 "geometricalDistanceFromSoma",
355 "geometrical distance of each segment from soma.",
360 "electrotonicDistanceFromSoma",
361 "geometrical distance of each segment from soma, as measured along "
367 "Vector of ObjIds of electrical compartments. Order matches order "
368 "of segments, and also matches the order of the electrotonic and "
369 "geometricalDistanceFromSoma vectors. ",
374 compartmentsFromExpression(
375 "compartmentsFromExpression",
376 "Vector of ObjIds of electrical compartments that match the "
377 "'path expression' pair in the argument string.",
382 valuesFromExpression(
383 "valuesFromExpression",
384 "Vector of values computed for each electrical compartment that "
385 "matches the 'path expression' pair in the argument string."
386 "This has 13 times the number of entries as # of compartments."
387 "For each compartment the entries are: \n"
388 "val, p, g, L, len, dia, maxP, maxG, maxL, x, y, z, 0",
393 spinesFromExpression(
394 "spinesFromExpression",
398 "Vector of ObjIds of compartments comprising spines/heads "
399 "that match the 'path expression' pair in the "
406 "spinesOnCompartment",
407 "Vector of ObjIds of spines shafts/heads sitting on the specified "
408 "electrical compartment. If each spine has a shaft and a head,"
409 "and there are 10 spines on the compartment, there will be 20 "
410 "entries in the returned vector, ordered "
411 "shaft0, head0, shaft1, head1, ... ",
416 parentCompartmentOfSpine(
417 "parentCompartmentOfSpine",
418 "Returns parent compartment of specified spine compartment."
419 "Both the spine head or its shaft will return the same parent.",
424 spineIdsFromCompartmentIds(
425 "spineIdsFromCompartmentIds",
426 "Vector of ObjIds of spine entries (FieldElements on this Neuron, "
427 "used for scaling) that map to the the specified "
428 "electrical compartments. If a bad compartment Id is given, the"
429 "corresponding spine entry is the root Id.",
437 "Build the reference segment tree structure using the child "
438 "compartments of the current Neuron. Fills in all the coords and "
439 "length constant information into the segments, for later use "
440 "when we build reduced compartment trees and channel "
441 "distributions. Should only be called once, since subsequent use "
442 "on a reduced model will lose the original full cell geometry. ",
446 "Assigns the spine and psd mesh to the Neuron. This is used "
447 "to build up a mapping from Spine entries on the Neuron to "
448 "chem spines and PSDs, so that volume change operations from "
449 "the Spine can propagate to the chem systems.",
453 "Assigns the Dsolves used by spine and PSD to the Neuron. "
455 "to handle the rescaling of diffusion rates when spines are "
474 "Field Element for spines. Used to handle dynamic "
475 "geometry changes in spines. ",
484 static Finfo* neuronFinfos[] =
493 &compartmentLengthInLambdas,
501 &channelDistribution,
502 &passiveDistribution,
506 &compartmentsFromExpression,
507 &valuesFromExpression,
508 &spinesFromExpression,
509 &spinesOnCompartment,
510 &parentCompartmentOfSpine,
511 &spineIdsFromCompartmentIds,
517 static string doc[] =
520 "Author",
"C H Chaitanya, Upi Bhalla",
521 "Description",
"Neuron - Manager for neurons. "
522 "Handles high-level specification of distribution of "
523 "spines, channels and passive properties. Also manages "
524 "spine resizing through a Spine FieldElement. ",
530 neuronFinfos,
sizeof( neuronFinfos ) /
sizeof(
Finfo* ),
533 sizeof(doc)/
sizeof(
string)
554 compartmentLengthInLambdas_( 0.2 ),
568 theta_( other.theta_ ),
570 maxP_( other.maxP_ ),
571 maxG_( other.maxG_ ),
572 maxL_( other.maxL_ ),
573 sourceFile_( other.sourceFile_ ),
574 compartmentLengthInLambdas_(other.compartmentLengthInLambdas_),
575 channelDistribution_( other.channelDistribution_ ),
576 passiveDistribution_( other.passiveDistribution_ ),
577 spineDistribution_( other.spineDistribution_ ),
588 const vector< string >& distrib )
591 vector< string > temp;
592 for (
unsigned int i = 0; i < distrib.size(); ++i )
594 if ( distrib[i] ==
"" )
596 if ( temp.size() < 4 )
598 cout <<
"Warning: Neuron::parseDistrib: <4 args: " <<
602 if ( temp.size() % 2 == 1 )
604 cout <<
"Warning: Neuron::parseDistrib: : odd # of args:"
605 << temp.size() << endl;
608 lines.push_back( temp );
613 temp.push_back( distrib[i] );
623 shell->
doAddMsg(
"Single", compt,
"channel", obj,
"channel" );
630 vector< ObjId > elist;
634 if ( elist.size() > 0 )
638 "single", obj,
"IkOut", elist[0],
"current" );
649 const vector< ObjId >& elist,
const vector< double >& val,
650 vector< ObjId >& mech )
653 Id proto(
"/library/" + name );
656 cout <<
"Warning: Neuron::buildFromProto: proto '"
657 << name <<
"' not found, skipping\n";
661 mech.resize( elist.size() );
662 for (
unsigned int i = 0; i < elist.size(); ++i )
671 obj = shell->
doCopy( proto, elist[i], name, 1,
false,
false );
681 double val,
double len,
double dia )
685 if ( field ==
"Gbar" )
690 else if ( field ==
"Ek" )
700 if ( field ==
"CaBasal" || field ==
"tau" || field ==
"thick" ||
701 field ==
"floor" || field ==
"ceiling" )
705 else if ( field ==
"B" )
720 double val,
const string& field,
double len,
double dia )
722 if ( field ==
"initVm" || field ==
"INITVM" )
727 if ( field ==
"Em" || field ==
"EM" )
734 if ( field ==
"Rm" || field ==
"Ra" || field ==
"Cm" )
738 else if ( field ==
"RM" )
742 else if ( field ==
"RA" )
746 else if ( field ==
"CM" )
752 cout <<
"Warning: setCompartmentParam: field '" << field <<
759 const vector< ObjId >& elist,
const vector< double >& val,
760 const string& field,
const string& expr )
765 for (
unsigned int i = 0; i < elist.size(); ++i )
772 double x = parser.
eval( val.begin() + j );
774 x, field, len, dia );
778 catch ( mu::Parser::exception_type& err )
780 cout << err.GetMsg() << endl;
785 const vector< ObjId >& mech,
786 const vector< ObjId >& elist,
const vector< double >& val,
787 const string& field,
const string& expr )
792 for (
unsigned int i = 0; i < elist.size(); ++i )
799 double x = parser.
eval( val.begin() + j );
804 catch ( mu::Parser::exception_type& err )
806 cout << err.GetMsg() << endl;
819 cout <<
"Warning:: Neuron::setRM: value must be +ve, is " << v << endl;
831 cout <<
"Warning:: Neuron::setRA: value must be +ve, is " << v << endl;
843 cout <<
"Warning:: Neuron::setCM: value must be +ve, is " << v << endl;
923 vector< double > ret(
segs_.size(), 0.0 );
924 for (
unsigned int i = 0; i <
segs_.size(); ++i )
931 vector< double > ret(
segs_.size(), 0.0 );
932 for (
unsigned int i = 0; i <
segs_.size(); ++i )
939 vector< double > ret(
segs_.size(), 0.0 );
940 for (
unsigned int i = 0; i <
segs_.size(); ++i )
947 vector< ObjId > ret(
segId_.size() );
948 for (
unsigned int i = 0; i <
segId_.size(); ++i )
963 vector< ObjId > elist;
964 vector< double > val;
965 unsigned long pos = line.find_first_of(
" \t" );
966 string path = line.substr( 0, pos );
967 string expr = line.substr( pos );
972 if ( elist.size() == 0 )
975 ret.reserve( elist.size() );
976 for (
unsigned int i = 0; i < elist.size(); ++i )
979 ret.push_back( elist[i] );
994 vector< ObjId > elist;
995 vector< double > val;
996 unsigned long pos = line.find_first_of(
" \t" );
997 string path = line.substr( 0, pos );
998 string expr = line.substr( pos );
1003 if ( elist.size() == 0 )
1010 const Eref& e,
string line )
const
1012 unsigned long pos = line.find_first_of(
" \t" );
1013 string path = line.substr( 0, pos );
1014 string expr = line.substr( pos );
1030 for ( vector< ObjId >::iterator
1031 i = temp.begin(); i != temp.end(); ++i )
1033 map< Id, unsigned int >::const_iterator si =
1036 assert( si->second <
segId_.size() );
1040 for ( vector< Id >::const_iterator j = s.begin(); j != s.end(); ++j )
1043 ret.push_back( *j );
1053 vector< ObjId > ret;
1054 map< Id, unsigned int >::const_iterator pos =
1060 for (
unsigned int i = 0; i < spines.size(); ++i )
1061 ret.push_back( spines[i] );
1069 for (
unsigned int comptIndex = 0; comptIndex <
allSpinesPerCompt_.size(); ++comptIndex )
1072 for (
unsigned int j = 0; j < v.size(); j++ )
1073 if ( v[j] == compt.
id )
1074 return segId_[ comptIndex ];
1080 const Eref& e, vector< ObjId > compt )
const
1082 vector< ObjId > ret;
1085 for (
unsigned int i = 0; i <
spines_.size(); ++i )
1087 for ( vector< Id >::const_iterator j =
spines_[i].begin(); j !=
spines_[i].end(); ++j )
1089 lookupSpine[ *j ] = i;
1093 for ( map< Id, unsigned int >::const_iterator k = lookupSpine.begin(); k != lookupSpine.end(); ++k )
1099 for ( vector< ObjId >::const_iterator j = compt.begin(); j != compt.end(); ++j )
1102 map< Id, unsigned int >::const_iterator k = lookupSpine.find( j->id );
1103 if ( k != lookupSpine.end() )
1110 ret.push_back(
ObjId() );
1117 const vector< string >& line,
1118 vector< ObjId >& elist,
1119 vector< double >& val )
1122 const string&
path = line[1];
1123 const string& expr = line[3];
1127 sort( elist.begin(), elist.end() );
1135 vector< vector< string > > lines;
1139 for (
unsigned int i = 0; i < lines.size(); ++i )
1141 vector< string >& temp = lines[i];
1142 vector< ObjId > elist;
1143 vector< double > val;
1146 vector< ObjId > mech( elist.size() );
1149 for (
unsigned int j = 2; j < temp.size(); j += 2 )
1165 vector< vector< string > > lines;
1169 for (
unsigned int i = 0; i < lines.size(); ++i )
1171 vector< string >& temp = lines[i];
1172 vector< ObjId > elist;
1173 vector< double > val;
1175 for (
unsigned int j = 2; j < temp.size(); j += 2 )
1191 vector< vector< string > > lines;
1195 for (
unsigned int i = 0; i < lines.size(); ++i )
1197 vector< ObjId > elist;
1198 vector< double > val;
1218 static const Finfo* raxialFinfo =
1220 static const Finfo* proximalFinfo =
1223 if (
id.element()->cinfo()->isA(
"CompartmentBase" ) )
1226 id.element()->getNeighbors( ret, raxialFinfo );
1227 if ( ret.size() == 1 )
1230 if (
id.element()->cinfo()->isA(
"SymCompartment" ) )
1232 id.element()->getNeighbors( ret, proximalFinfo );
1233 if ( ret.size() == 1 )
1242 const vector< Id >& kids, map< Id, unsigned int >& segIndex )
1247 double maxDia = 0.0;
1248 unsigned int numKids = 0;
1249 for (
unsigned int i = 0; i < kids.size(); ++i )
1251 const Id& k = kids[i];
1254 segIndex[ k ] = numKids++;
1256 if ( s.find(
"soma" ) != s.npos ||
1257 s.find(
"Soma" ) != s.npos ||
1258 s.find(
"SOMA" ) != s.npos )
1276 const map< Id, unsigned int >& segIndex,
1277 const vector< Id >& kids )
1280 for (
unsigned int i = 0; i < kids.size(); ++i )
1282 const Id& k = kids[i];
1290 unsigned int paIndex = ~0U;
1294 map< Id, unsigned int >::const_iterator
1295 j = segIndex.find( pa );
1296 if ( j != segIndex.end() )
1298 paIndex = j->second;
1305 SwcSegment( i, comptType, x, y, z, dia/2.0, paIndex ) );
1312 SwcSegment&
self, vector< SwcSegment >& segs,
1313 const vector< Id >& lookupId,
1314 double len,
double L,
double pSoma,
double eSoma )
1316 self.setCumulativeDistance( len, L, pSoma, eSoma );
1317 for (
unsigned int i = 0; i <
self.kids().size(); ++i )
1320 double segmentLength = kid.
distance(
self );
1321 double p = pSoma + segmentLength;
1322 Id kidId = lookupId[
self.kids()[i] ];
1326 double electrotonicLength = sqrt( Ra / Rm );
1327 double e = eSoma + electrotonicLength;
1329 segmentLength, electrotonicLength, p, e );
1341 double L = sqrt( Ra / Rm );
1343 for (
unsigned int i = 0; i <
segs_.size(); ++i )
1345 segs_[i].setGeometricalDistanceFromSoma(
segs_[0] );
1350 for (
unsigned int i = 0; i <
segs_.size(); ++i )
1352 double p =
segs_[i].getPathDistFromSoma();
1354 double g =
segs_[i].getGeomDistFromSoma();
1356 double L =
segs_[i].getElecDistFromSoma();
1366 sort( kids.begin(), kids.end() );
1369 if ( kids.size() == 0 || soma_ ==
Id() )
1371 cout <<
"Error: Neuron::buildSegmentTree( " << e.
id().
path() <<
1372 " ): \n Valid neuronal model not found.\n";
1377 for (
unsigned int i = 0; i <
segs_.size(); ++i )
1379 if (
segs_[i].parent() == ~0U )
1388 for (
unsigned int i = 0; i <
segs_.size(); ++i )
1390 segs_[i].figureOutType();
1395 cout <<
"Warning: Neuron.cpp: buildTree: numPa = " << numPa << endl;
1399 for ( map< Id, unsigned int >::const_iterator
1402 assert( i->second <
segId_.size() );
1403 segId_[ i->second ] = i->first;
1414 cout <<
"Error: Neuron::setSpineAndPsdMesh: '" <<
1415 spineMesh.
path() <<
"' is not a SpineMesh\n";
1420 cout <<
"Error: Neuron::setSpineAndPsdMesh: '" <<
1421 psdMesh.
path() <<
"' is not a PsdMesh\n";
1426 if ( spineStoich ==
Id() || psdStoich ==
Id() )
1428 cout <<
"Error: Neuron::setSpineAndPsdMesh: Stoich child not found\n";
1433 spineMesh,
"elecComptList" );
1435 psdMesh,
"elecComptList" );
1436 assert( spineList.size()== psdList.size() );
1437 map< Id, unsigned int > spineMap;
1438 for (
unsigned int i = 0; i <
spines_.size(); ++i )
1440 assert(
spines_[i].size() > 1 );
1441 spineMap[
spines_[i][1] ] = i;
1447 for(
unsigned int i = 0; i < spineList.size(); ++i )
1449 map< Id, unsigned int >::iterator j = spineMap.find( spineList[i]);
1450 if ( j == spineMap.end() )
1452 cout <<
"Error: Neuron::setSpineAndPsdMesh: spine '" <<
1453 spineList[i].path() <<
"' not found on Neuron\n";
1479 const string& expn, vector< double >& val )
const
1486 unsigned int valIndex = 0;
1493 for ( vector< ObjId >::const_iterator
1494 i = elist.begin(); i != elist.end(); ++i )
1496 if ( i->element()->cinfo()->isA(
"CompartmentBase" ) )
1498 map< Id, unsigned int >:: const_iterator j =
1504 assert( j->second <
segs_.size() );
1506 segs_[j->second].getPathDistFromSoma();
1508 segs_[j->second].getGeomDistFromSoma();
1510 segs_[j->second].getElecDistFromSoma();
1523 val.begin() + valIndex );
1529 catch ( mu::Parser::exception_type& err )
1531 cout << err.GetMsg() << endl;
1548 static const double EPSILON = 1e-20;
1556 Vec temp( x1-x0, y1-y0, z1-z0 );
1557 double len = temp.
length();
1558 z =
Vec( temp.
a0()/len, temp.
a1()/len, temp.
a2()/len );
1563 Vec temp2( x0 - sx0, y0-sy0, z0-sz0 );
1565 double ylen = y2.
length();
1567 while ( ylen < EPSILON )
1569 Vec t( ytemp , sqrt( 2.0 ), 0.0 );
1574 y =
Vec( y2.
a0()/ylen, y2.
a1()/ylen, y2.
a2()/ylen );
1584 vector< Vec >& coords,
1585 Vec& parentPos,
double pos,
double angle,
1588 double c = cos( angle );
1589 double s = sin( angle );
1590 double omc = 1.0 - c;
1592 Vec rot0( z.
a0()*z.
a0()*omc + c,
1593 z.
a1()*z.
a0()*omc - z.
a2()*s ,
1594 z.
a2()*z.
a0()*omc + z.
a1()*s );
1597 z.
a1()*z.
a1()*omc + c,
1598 z.
a2()*z.
a1()*omc - z.
a0()*s );
1601 z.
a1()*z.
a2()*omc + z.
a0()*s,
1602 z.
a2()*z.
a2()*omc + c );
1604 Vec translation = z * pos + parentPos;
1606 vector< Vec > ret( coords.size() );
1607 for (
unsigned int i = 0; i < coords.size(); ++i )
1609 ret[i] =
Vec( rot0.dotProduct( coords[i] ) + translation.a0(),
1610 rot1.dotProduct( coords[i] ) + translation.a1(),
1611 rot2.dotProduct( coords[i] ) + translation.a2() );
1614 assert( spineCompts.size() * 2 == ret.size() );
1616 for (
unsigned int i = 0; i < spineCompts.size(); ++i )
1618 unsigned int j = 2 * i;
1650 double pos,
double angle,
1657 stringstream sstemp;
1659 string kstr = sstemp.str();
1660 Id spine = shell->
doCopy( spineProto, parentObject,
"_spine" + kstr,
1668 Vec ppos( x0, y0, z0 );
1671 vector< Vec > coords;
1673 for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i )
1675 if ( i->element()->cinfo()->isA(
"CompartmentBase" ) )
1677 i->element()->setName( i->element()->getName() + kstr );
1681 coords.push_back(
Vec( x0 + parentRadius, y0, z0 ) );
1695 coords.push_back(
Vec( x + parentRadius, y, z ) );
1697 shell->
doMove( *i, parentObject );
1698 ret.push_back( *i );
1702 for( vector< Vec >::iterator i = coords.begin(); i != coords.end(); ++i)
1705 shell->
doAddMsg(
"Single", parentCompt,
"axial", kids[0],
"raxial" );
1716 string findArg(
const vector<string>& line,
const string& field )
1719 assert( (line.size() % 2) != 1 );
1720 for (
unsigned int i = 2; i < line.size(); i+=2 )
1721 if ( line[i] == field )
1724 if ( field ==
"spacing" )
1728 else if ( field ==
"spacingDistrib" )
1732 else if ( field ==
"size" )
1736 else if ( field ==
"sizeDistrib" )
1740 else if ( field ==
"angle" )
1744 else if ( field ==
"angleDistrib" )
1746 ret =
"6.283185307";
1748 else if ( field ==
"rotation" )
1752 else if ( field ==
"rotationDistrib" )
1754 ret =
"6.283185307";
1756 else if ( field ==
"shaftLen" )
1760 else if ( field ==
"shaftDia" )
1764 else if ( field ==
"headLen" )
1768 else if ( field ==
"headDia" )
1772 else if ( field ==
"theta" )
1776 else if ( field ==
"phi" )
1778 ret =
"1.5707963268";
1784 static void addPos(
unsigned int segIndex,
unsigned int eIndex,
1785 double spacing,
double minSpacing,
1787 vector< unsigned int >& seglistIndex,
1788 vector< unsigned int >& elistIndex,
1789 vector< double >& pos )
1791 if ( minSpacing < spacing * 0.1 && minSpacing < 1e-7 )
1792 minSpacing = spacing * 0.1;
1793 if ( minSpacing > spacing * 0.5 )
1794 minSpacing = spacing * 0.5;
1795 unsigned int n = 1 + dendLength / minSpacing;
1796 double dx = dendLength / n;
1797 for(
unsigned int i = 0; i < n; ++i )
1802 seglistIndex.push_back( segIndex );
1803 elistIndex.push_back( eIndex );
1804 pos.push_back( i * dx + dx*0.5 );
1842 const vector< double >& val,
1843 vector< unsigned int >& seglistIndex,
1844 vector< unsigned int >& elistIndex,
1845 vector< double >& pos,
1846 const vector< string >& line )
const
1848 string distribExpr =
findArg( line,
"spacingDistrib" );
1850 elistIndex.resize( 0 );
1856 for (
unsigned int i = 0; i < elist.size(); ++i )
1862 double spacingDistrib = parser.
eval( val.begin() + j );
1863 if ( spacingDistrib > spacing || spacingDistrib < 0 )
1865 cout <<
"Warning: Neuron::makeSpacingDistrib: " <<
1866 "0 < " << spacingDistrib <<
" < " << spacing <<
1867 " fails on " << elist[i].path() <<
". Using 0.\n";
1868 spacingDistrib = 0.0;
1870 map< Id, unsigned int>::const_iterator
1871 lookupDend =
segIndex_.find( elist[i] );
1874 double dendLength =
segs_[lookupDend->second].length();
1875 addPos( lookupDend->second, i,
1876 spacing, spacingDistrib, dendLength,
1877 seglistIndex, elistIndex, pos );
1882 catch ( mu::Parser::exception_type& err )
1884 cout << err.GetMsg() << endl;
1889 const vector< double >& val,
1890 vector< unsigned int >& elistIndex,
1891 vector< double >& theta,
1892 const vector< string >& line )
1894 string angleExpr =
findArg( line,
"angle" );
1895 string angleDistribExpr =
findArg( line,
"angleDistrib" );
1899 theta.resize( elistIndex.size(), 0.0 );
1904 nuParser distribParser( angleDistribExpr );
1905 unsigned int lastIndex = ~0U;
1907 double angleDistrib = 0;
1908 for (
unsigned int k = 0; k < elistIndex.size(); ++k )
1910 unsigned int i = elistIndex[k];
1911 if ( i != lastIndex )
1915 angle = angleParser.
eval( val.begin() + j );
1916 angleDistrib = distribParser.
eval( val.begin() + j);
1920 if ( angleDistrib > 0 )
1921 theta[k] = angle + (
moose::mtrand() - 0.5 ) * angleDistrib;
1926 catch ( mu::Parser::exception_type& err )
1928 cout << err.GetMsg() << endl;
1933 const vector< double >& val,
1934 vector< unsigned int >& elistIndex,
1935 vector< double >& size,
1936 const vector< string >& line )
1938 string sizeExpr =
findArg( line,
"size" );
1939 string sizeDistribExpr =
findArg( line,
"sizeDistrib" );
1941 size.resize( elistIndex.size(), 0.0 );
1946 nuParser distribParser( sizeDistribExpr );
1947 unsigned int lastIndex = ~0U;
1949 double sizeDistrib = 0;
1950 for (
unsigned int k = 0; k < elistIndex.size(); ++k )
1952 unsigned int i = elistIndex[k];
1953 if ( i != lastIndex )
1957 sz = sizeParser.
eval( val.begin() + j );
1958 sizeDistrib = distribParser.
eval( val.begin() + j);
1962 if ( sizeDistrib > 0 )
1968 catch ( mu::Parser::exception_type& err )
1970 cout << err.GetMsg() << endl;
1975 const vector< double >& val,
const vector< string >& line )
1977 Id spineProto(
"/library/spine" );
1979 if ( spineProto ==
Id() )
1981 cout <<
"Warning: Neuron::installSpines: Unable to find prototype spine: /library/spine\n";
1986 vector< unsigned int > elistIndex;
1987 vector< double > pos;
1988 vector< double > theta;
1989 vector< double > size;
1990 pos.reserve( elist.size() );
1991 elistIndex.reserve( elist.size() );
2004 x, y, z, size[k], k )
2017 for (
unsigned int i = 0; i <
spines_.size(); ++i )
2049 static vector< Id > fail;
2056 double lenScale,
double diaScale )
const
2058 double volScale = lenScale * diaScale * diaScale;
2068 cout <<
"Error: Neuron::scaleBufAndRates: spineNum too big: " <<
2088 volScale = diaScale * diaScale;
2095 double len,
double dia)
const
2097 double diffScale = dia * dia * 0.25 *
PI / len;
2107 double len,
double dia)
const
2109 double vol = len * dia * dia *
PI * 0.25;
2112 double diffScale = dia * dia * 0.25 *
PI / (len/2.0);
2119 double psdVol = thick * dia * dia *
PI * 0.25;
2121 meshIndex, psdVol );
2127 psdDsolve_,
"setDiffVol1", meshIndex, psdVol );
2129 psdDsolve_,
"setDiffScale", meshIndex, diffScale );
unsigned int getNumCompartments() const
int wildcardFind(const string &path, vector< ObjId > &ret)
vector< unsigned int > spineToMeshOrdering_
looks up spine/psd mesh index from FieldIndex of selected spine.
void setPassiveDistribution(const Eref &e, vector< string > v)
static double H(double arg)
static ObjId parent(const Eref &e)
static void setMechParams(const vector< ObjId > &mech, const vector< ObjId > &elist, const vector< double > &val, const string &field, const string &expr)
static bool set(const ObjId &dest, const string &field, L index, A arg)
void scaleHeadDiffusion(unsigned int spineNum, double len, double dia) const
Scale the diffusion parameters due to a change in the head dimensions.
static void fillSegments(vector< SwcSegment > &segs, const map< Id, unsigned int > &segIndex, const vector< Id > &kids)
static void assignParam(Id obj, const string &field, double val, double len, double dia)
double compartmentLengthInLambdas_
void setSpineAndPsdDsolve(Id spineDsolve, Id psdDsolve)
Element * element() const
Synonym for Id::operator()()
static void doClassSpecificMessaging(Shell *shell, Id obj, ObjId compt)
bool parseDistrib(vector< vector< string > > &lines, const vector< string > &distrib)
void makeSpacingDistrib(const vector< ObjId > &elist, const vector< double > &val, vector< unsigned int > &seglistIndex, vector< unsigned int > &elistIndex, vector< double > &pos, const vector< string > &line) const
vector< double > getPathDistFromSoma() const
std::string path(const std::string &separator="/") const
unsigned int value() const
vector< string > channelDistribution_
unsigned int getNumBranches() const
vector< string > passiveDistribution_
void installSpines(const vector< ObjId > &elist, const vector< double > &val, const vector< string > &line)
vector< ObjId > getExprElist(const Eref &e, string line) const
unsigned int dataIndex() const
static const Cinfo * find(const std::string &name)
void buildElist(const Eref &e, const vector< string > &line, vector< ObjId > &elist, vector< double > &val)
Id doCopy(Id orig, ObjId newParent, string newName, unsigned int n, bool toGlobal, bool copyExtMsgs)
Returns the Id of the root of the copied tree upon success.
const double FaradayConst
static Id child(const Eref &e, const string &name)
void setSourceFile(string v)
Spine * lookupSpine(unsigned int index)
vector< vector< Id > > allSpinesPerCompt_
Id of each compt in each spine.
void evalExprForElist(const vector< ObjId > &elist, const string &expn, vector< double > &val) const
static void children(const Eref &e, vector< Id > &ret)
static bool set(const ObjId &dest, const string &field, A arg)
static void traverseCumulativeDistance(SwcSegment &self, vector< SwcSegment > &segs, const vector< Id > &lookupId, double len, double L, double pSoma, double eSoma)
Recursive function to fill in cumulative distances from soma.
double eval(vector< double >::const_iterator arg0)
map< Id, unsigned int > segIndex_
Map to look up Seg index from Id of associated compt.
static void reorientSpine(vector< Id > &spineCompts, vector< Vec > &coords, Vec &parentPos, double pos, double angle, Vec &x, Vec &y, Vec &z)
static bool buildFromProto(const string &name, const vector< ObjId > &elist, const vector< double > &val, vector< ObjId > &mech)
static const Cinfo * initCinfo()
Vec crossProduct(const Vec &other) const
vector< Id > psdStoich_
Id of stoich associated with each PSD. Typically all the same.
Spine spineEntry_
Id of the Dsolve for the PSD compt.
const vector< Id > & spineIds(unsigned int index) const
vector< string > getChannelDistribution(const Eref &e) const
static Id getComptParent(Id id)
string findArg(const vector< string > &line, const string &field)
bool doubleEq(double x, double y)
double getCompartmentLengthInLambdas() const
static void makeSizeDistrib(const vector< ObjId > &elist, const vector< double > &val, vector< unsigned int > &elistIndex, vector< double > &size, const vector< string > &line)
void setSpineAndPsdMesh(Id spineMesh, Id psdMesh)
Fills up vector of segments. First entry is soma.
valArgs
Defines the order of arguments in the val array.
static const Cinfo * initCinfo()
static double coordSystem(Id soma, Id dend, Vec &x, Vec &y, Vec &z)
void scaleShaftDiffusion(unsigned int spineNum, double len, double dia) const
Scale the diffusion parameters due to a change in the shaft dimensions.
vector< ObjId > getSpinesFromExpression(const Eref &e, string line) const
string getSourceFile() const
bool matchBeforeBrace(ObjId id, const string &wild)
bool isA(const string &ancestor) const
vector< vector< Id > > spines_
nuParser(const string &expr)
vector< double > getExprVal(const Eref &e, string line) const
double distance(const SwcSegment &other) const
const Cinfo * cinfo() const
static void addChannelMessage(Id chan)
vector< string > getSpineDistribution(const Eref &e) const
vector< string > getPassiveDistribution(const Eref &e) const
ObjId getParentCompartmentOfSpine(const Eref &e, ObjId compt) const
void setSpineDistribution(const Eref &e, vector< string > v)
void setChannelDistribution(const Eref &e, vector< string > v)
vector< SwcBranch > branches_
vector< ObjId > getSpineIdsFromCompartmentIds(const Eref &e, vector< ObjId > compt) const
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Id fillSegIndex(const vector< Id > &kids, map< Id, unsigned int > &segIndex)
vector< ObjId > getCompartments() const
void setCompartmentLengthInLambdas(double v)
static void makeAngleDistrib(const vector< ObjId > &elist, const vector< double > &val, vector< unsigned int > &elistIndex, vector< double > &theta, const vector< string > &line)
vector< unsigned int > spineParentSegIndex_
Look up seg index of parent compartment, from index of spine.
Id psdDsolve_
Id of the Dsolve for the head compt.
double mtrand(void)
Generate a random double between 0 and 1.
void setNumSpines(unsigned int num)
static void setCompartmentParams(const vector< ObjId > &elist, const vector< double > &val, const string &field, const string &expr)
void buildSegmentTree(const Eref &e)
Fills up vector of segments. First entry is soma.
unsigned int getNumSpines() const
static void assignSingleCompartmentParams(ObjId compt, double val, const string &field, double len, double dia)
static A get(const ObjId &dest, const string &field)
static const Cinfo * initCinfo()
void updateSegmentLengths()
static void addPos(unsigned int segIndex, unsigned int eIndex, double spacing, double minSpacing, double dendLength, vector< unsigned int > &seglistIndex, vector< unsigned int > &elistIndex, vector< double > &pos)
Add entries into the pos vector for a given compartment i.
vector< ObjId > getSpinesOnCompartment(const Eref &e, ObjId compt) const
vector< Id > spineStoich_
Id of stoich associated with each spine. Typically all the same.
static vector< Id > addSpine(Id parentCompt, Id spineProto, double pos, double angle, Vec &x, Vec &y, Vec &z, double size, unsigned int k)
const string & getName() const
void scaleBufAndRates(unsigned int spineNum, double lenScale, double diaScale) const
static const unsigned int numVal
vector< SwcSegment > segs_
Id of compartment in each Seg entry, below.
static const Cinfo * neuronCinfo
vector< string > spineDistribution_
const Finfo * findFinfo(const string &name) const
vector< double > getGeomDistFromSoma() const
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2)
void doMove(Id orig, ObjId newParent)
vector< double > getElecDistFromSoma() const