MOOSE - Multiscale Object Oriented Simulation Environment
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NeuroMesh.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2011 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include <cctype>
11 #include "header.h"
12 #include "SparseMatrix.h"
13 #include "../utility/Vec.h"
14 
15 #include "ElementValueFinfo.h"
16 #include "Boundary.h"
17 #include "MeshEntry.h"
18 #include "ChemCompt.h"
19 #include "MeshCompt.h"
20 #include "CubeMesh.h"
21 #include "CylBase.h"
22 #include "NeuroNode.h"
23 #include "NeuroMesh.h"
24 #include "SpineEntry.h"
25 #include "SpineMesh.h"
26 #include "EndoMesh.h"
27 #include "../utility/numutil.h"
28 #include "../utility/strutil.h"
29 #include "../shell/Wildcard.h"
30 
31 static SrcFinfo3< vector< Id >, vector< Id >, vector< unsigned int > >*
33 {
34  static SrcFinfo3< vector< Id >, vector< Id >, vector< unsigned int > >
36  "spineListOut",
37  "Request SpineMesh to construct self based on list of electrical "
38  "compartments that this NeuroMesh has determined are spine shaft "
39  "and spine head respectively. Also passes in the info about where "
40  "each spine is connected to the NeuroMesh. "
41  "Arguments: shaft compartment Ids, head compartment Ids,"
42  "index of matching parent voxels for each spine"
43  );
44  return &spineListOut;
45 }
46 
47 static SrcFinfo3< vector< double >, vector< Id >, vector< unsigned int > >*
49 {
51  vector< Id >, vector< unsigned int > >
52  psdListOut(
53  "psdListOut",
54  "Tells PsdMesh to build a mesh. "
55  "Arguments: (Cell Id, Coordinates of each psd, "
56  "Id of electrical compartment mapped to each voxel, "
57  "index of matching parent voxels for each spine.) "
58  "The coordinates each have 8 entries:"
59  "xyz of centre of psd, xyz of vector perpendicular to psd, "
60  "psd diameter, "
61  " diffusion distance from parent compartment to PSD"
62  );
63  return &psdListOut;
64 }
65 
67 {
69  // Field Definitions
72  "subTree",
73  "Set of compartments in which to embed chemical reaction "
74  "systems. If the compartments happen to be contiguous"
75  "then also set up diffusion between them. Can also"
76  "handle cases where the same cell is divided into multiple"
77  "non-diffusively-coupled compartments",
80  );
81  static ElementValueFinfo< NeuroMesh, string > subTreePath(
82  "subTreePath",
83  "Set of compartments to model, defined as a path string. "
84  "If they happen to be contiguous "
85  "then also set up diffusion between the compartments. Can also"
86  "handle cases where the same cell is divided into multiple"
87  "non-diffusively-coupled compartments",
90  );
91  static ValueFinfo< NeuroMesh, bool > separateSpines(
92  "separateSpines",
93  "Flag: when separateSpines is true, the traversal separates "
94  "any compartment with the strings "
95  "'spine', 'head', 'shaft' or 'neck' in its name,"
96  "Allows to set up separate mesh for spines, based on the "
97  "same cell model. Requires for the spineListOut message to"
98  "be sent to the target SpineMesh object.",
101  );
103  "numSegments",
104  "Number of cylindrical/spherical segments in model",
106  );
108  "numDiffCompts",
109  "Number of diffusive compartments in model",
111  );
113  "parentVoxel",
114  "Vector of indices of parents of each voxel.",
116  );
117  static ReadOnlyValueFinfo< NeuroMesh, vector< Id > > elecComptMap(
118  "elecComptMap",
119  "Vector of Ids of electrical compartments that map to each "
120  "voxel. This is necessary because the order of the IDs may "
121  "differ from the ordering of the voxels. Additionally, there "
122  "are typically many more voxels than there are electrical "
123  "compartments. So many voxels point to the same elecCompt.",
125  );
126  static ReadOnlyValueFinfo< NeuroMesh, vector< Id > > elecComptList(
127  "elecComptList",
128  "Vector of Ids of all electrical compartments in this "
129  "NeuroMesh. Ordering is as per the tree structure built in "
130  "the NeuroMesh, and may differ from Id order. Ordering "
131  "matches that used for startVoxelInCompt and endVoxelInCompt",
133  );
135  "startVoxelInCompt",
136  "Index of first voxel that maps to each electrical "
137  "compartment. Each elecCompt has one or more voxels. "
138  "The voxels in a compartment are numbered sequentially.",
140  );
142  "endVoxelInCompt",
143  "Index of end voxel that maps to each electrical "
144  "compartment. In keeping with C and Python convention, this "
145  "is one more than the last voxel. "
146  "Each elecCompt has one or more voxels. "
147  "The voxels in a compartment are numbered sequentially.",
149  );
150 
151  static ReadOnlyValueFinfo< NeuroMesh, vector< int > > spineVoxelOnDendVoxel(
152  "spineVoxelOnDendVoxel",
153  "Voxel index of spine voxel on each dend voxel. Assume that "
154  "there is never more than one spine per dend voxel. If no "
155  "spine present, the entry is -1. Note that the "
156  "same index is used both for spine head and PSDs.",
158  );
159 
161  vector< unsigned int > > dendVoxelsOnCompartment(
162  "dendVoxelsOnCompartment",
163  "Returns vector of all chem voxels on specified electrical "
164  "compartment of the dendrite. Returns empty vec if none "
165  "found, or if the compartment isn't on the dendrite.",
167  );
168 
169  static ReadOnlyLookupValueFinfo< NeuroMesh, ObjId,
170  vector< unsigned int > > spineVoxelsOnCompartment(
171  "spineVoxelsOnCompartment",
172  "Returns vector of all chem voxels on specified electrical "
173  "compartment, which should be a spine head or shaft . "
174  "Returns empty vec if no chem voxels "
175  "found, or if the compartment isn't on the dendrite. "
176  "Note that spine and PSD voxel indices are the same for a "
177  "given spine head.",
179  );
180 
181  static ValueFinfo< NeuroMesh, double > diffLength(
182  "diffLength",
183  "Diffusive length constant to use for subdivisions. "
184  "The system will"
185  "attempt to subdivide cell using diffusive compartments of"
186  "the specified diffusion lengths as a maximum."
187  "In order to get integral numbers"
188  "of compartments in each segment, it may subdivide more "
189  "finely."
190  "Uses default of 0.5 microns, that is, half typical lambda."
191  "For default, consider a tau of about 1 second for most"
192  "reactions, and a diffusion const of about 1e-12 um^2/sec."
193  "This gives lambda of 1 micron",
196  );
197 
198  static ValueFinfo< NeuroMesh, string > geometryPolicy(
199  "geometryPolicy",
200  "Policy for how to interpret electrical model geometry (which "
201  "is a branching 1-dimensional tree) in terms of 3-D constructs"
202  "like spheres, cylinders, and cones."
203  "There are three options, default, trousers, and cylinder:"
204  "default mode:"
205  " - Use frustrums of cones. Distal diameter is always from compt dia."
206  " - For linear dendrites (no branching), proximal diameter is "
207  " diameter of the parent compartment"
208  " - For branching dendrites and dendrites emerging from soma,"
209  " proximal diameter is from compt dia. Don't worry about overlap."
210  " - Place somatic dendrites on surface of spherical soma, or at ends"
211  " of cylindrical soma"
212  " - Place dendritic spines on surface of cylindrical dendrites, not"
213  " emerging from their middle."
214  "trousers mode:"
215  " - Use frustrums of cones. Distal diameter is always from compt dia."
216  " - For linear dendrites (no branching), proximal diameter is "
217  " diameter of the parent compartment"
218  " - For branching dendrites, use a trouser function. Avoid overlap."
219  " - For soma, use some variant of trousers. Here we must avoid overlap"
220  " - For spines, use a way to smoothly merge into parent dend. Radius of"
221  " curvature should be similar to that of the spine neck."
222  " - Place somatic dendrites on surface of spherical soma, or at ends"
223  " of cylindrical soma"
224  " - Place dendritic spines on surface of cylindrical dendrites, not"
225  " emerging from their middle."
226  "cylinder mode:"
227  " - Use cylinders. Diameter is just compartment dia."
228  " - Place somatic dendrites on surface of spherical soma, or at ends"
229  " of cylindrical soma"
230  " - Place dendritic spines on surface of cylindrical dendrites, not"
231  " emerging from their middle."
232  " - Ignore spatial overlap.",
235  );
236 
238  // MsgDest Definitions
240 
242  // Field Elements
244 
245  static Finfo* neuroMeshFinfos[] =
246  {
247  &subTree, // Value
248  &subTreePath, // Value
249  &separateSpines, // Value
250  &numSegments, // ReadOnlyValue
251  &numDiffCompts, // ReadOnlyValue
252  &parentVoxel, // ReadOnlyValue
253  &elecComptList, // ReadOnlyValue
254  &elecComptMap, // ReadOnlyValue
255  &startVoxelInCompt, // ReadOnlyValue
256  &endVoxelInCompt, // ReadOnlyValue
257  &spineVoxelOnDendVoxel, // ReadOnlyValue
258  &dendVoxelsOnCompartment, // ReadOnlyLookupValue
259  &spineVoxelsOnCompartment, // ReadOnlyLookupValue
260  &diffLength, // Value
261  &geometryPolicy, // Value
262  spineListOut(), // SrcFinfo
263  psdListOut(), // SrcFinfo
264  };
265 
266  static Dinfo< NeuroMesh > dinfo;
267  static Cinfo neuroMeshCinfo (
268  "NeuroMesh",
270  neuroMeshFinfos,
271  sizeof( neuroMeshFinfos ) / sizeof ( Finfo* ),
272  &dinfo
273  );
274 
275  return &neuroMeshCinfo;
276 }
277 
279 // Basic class Definitions
281 
283 
285 // Class stuff.
288  :
289  nodes_(1),
290  subTreePath_( "Undefined" ),
291  nodeIndex_(1, 0 ),
292  vs_( 1, NA * 1e-9 ),
293  area_( 1, 1.0e-12 ),
294  length_( 1, 1.0e-6 ),
295  diffLength_( 1.0e-6 ),
296  separateSpines_( false ),
297  geometryPolicy_( "default" ),
298  surfaceGranularity_( 0.1 ),
299  parentVoxel_(1, -1)
300 {
301  nodes_[0].setLength( diffLength_ );
302  nodes_[0].setDia( diffLength_ );
303  nodes_[0].setNumDivs( 1 );
304 }
305 
307  :
308  diffLength_( other.diffLength_ ),
309  separateSpines_( other.separateSpines_ ),
310  geometryPolicy_( other.geometryPolicy_ ),
311  surfaceGranularity_( other.surfaceGranularity_ )
312 {
313  ;
314 }
315 
317 {
318  nodes_ = other.nodes_;
319  nodeIndex_ = other.nodeIndex_;
320  vs_ = other.vs_;
321  area_ = other.area_;
322  length_ = other.length_;
323  diffLength_ = other.diffLength_;
326  return *this;
327 }
328 
330 {
331  ;
332 }
333 
335 // Field assignment stuff
337 
344 {
345  unsigned int startFid = 0;
346  if ( nodes_.size() <= 1 ) // One for soma and one for dummy pa of soma
347  {
348  buildStencil();
349  return;
350  }
351  for ( vector< NeuroNode >::iterator i = nodes_.begin();
352  i != nodes_.end(); ++i )
353  {
354  if ( !i->isDummyNode() )
355  {
356  double len = i->getLength();
357  unsigned int numDivs = floor( 0.5 + len / diffLength_ );
358  if ( numDivs < 1 )
359  numDivs = 1;
360  i->setNumDivs( numDivs );
361  i->setStartFid( startFid );
362  startFid += numDivs;
363  }
364  }
365  nodeIndex_.resize( startFid );
366  for ( unsigned int i = 0; i < nodes_.size(); ++i )
367  {
368  if ( !nodes_[i].isDummyNode() )
369  {
370  unsigned int end = nodes_[i].startFid() +nodes_[i].getNumDivs();
371  assert( end <= startFid );
372  assert( nodes_[i].getNumDivs() > 0 );
373  for ( unsigned int j = nodes_[i].startFid(); j < end; ++j )
374  nodeIndex_[j] = i;
375  }
376  }
377  // Assign volumes and areas
378  vs_.resize( startFid );
379  area_.resize( startFid );
380  length_.resize( startFid );
381  for ( unsigned int i = 0; i < nodes_.size(); ++i )
382  {
383  const NeuroNode& nn = nodes_[i];
384  if ( !nn.isDummyNode() )
385  {
386  assert( nn.parent() < nodes_.size() );
387  const NeuroNode& parent = nodes_[ nn.parent() ];
388  for ( unsigned int j = 0; j < nn.getNumDivs(); ++j )
389  {
390  vs_[j + nn.startFid()] = nn.voxelVolume( parent, j );
391  area_[j + nn.startFid()] = nn.getMiddleArea( parent, j);
392  length_[j + nn.startFid()] = nn.getVoxelLength();
393  }
394  }
395  }
396  buildStencil();
397 }
398 
399 void NeuroMesh::setDiffLength( double v )
400 {
401  diffLength_ = v;
402  updateCoords();
403 }
404 
406 {
407  return diffLength_;
408 }
409 
411 {
412  // STL magic! Converts the string v to lower case. Unfortunately
413  // someone has overloaded tolower so it can have one or two args, so
414  // this marvellous construct is useless.
415  // std::transform( v.begin(), v.end(), v.begin(), std::tolower );
416  for( string::iterator i = v.begin(); i != v.end(); ++i )
417  *i = tolower( *i );
418 
419  if ( !( v == "cylinder" || v == "trousers" || v == "default" ) )
420  {
421  cout << "Warning: NeuroMesh::setGeometryPolicy( " << v <<
422  " ):\n Mode must be one of cylinder, trousers, or default."
423  "Using default\n";
424  v = "default";
425  }
426 
427  if ( v == geometryPolicy_ )
428  return;
429  geometryPolicy_ = v;
430  bool isCylinder = ( v == "cylinder" );
431  for ( vector< NeuroNode >::iterator
432  i = nodes_.begin(); i != nodes_.end(); ++i )
433  i->setIsCylinder( isCylinder );
434 }
435 
437 {
438  return geometryPolicy_;
439 }
440 
441 unsigned int NeuroMesh::innerGetDimensions() const
442 {
443  return 3;
444 }
445 
446 Id tryParent( Id id, const string& msgName )
447 {
448  const Finfo* finfo = id.element()->cinfo()->findFinfo( msgName );
449  if ( !finfo )
450  return Id();
451  vector< Id > ret;
452  id.element()->getNeighbors( ret, finfo );
453  assert( ret.size() <= 1 );
454  if ( ret.size() == 1 )
455  return ret[0];
456  return Id();
457 }
458 
460 {
461  if ( id.element()->cinfo()->isA( "Compartment" ) )
462  return tryParent( id, "axialOut" );
463  if ( id.element()->cinfo()->isA( "SymCompartment" ) )
464  return tryParent( id, "proximalOut" );
465  return Id();
466 }
467 
468 Id NeuroMesh::putSomaAtStart( Id origSoma, unsigned int maxDiaIndex )
469 {
470  Id soma = origSoma;
471  if ( nodes_[maxDiaIndex].elecCompt() == soma ) // Happy, happy
472  {
473  ;
474  }
475  else if ( soma == Id() )
476  {
477  soma = nodes_[maxDiaIndex].elecCompt();
478  }
479  else // Disagreement. Ugh.
480  {
481  string name = nodes_[ maxDiaIndex ].elecCompt().element()->getName();
482  // OK, somehow this model has more than one soma compartment.
483  if ( moose::strncasecmp( name.c_str(), "soma", 4 ) == 0 )
484  {
485  soma = nodes_[maxDiaIndex].elecCompt();
486  }
487  else
488  {
489  cout << "Warning: NeuroMesh::putSomaAtStart: named 'soma' compartment isn't biggest\n";
490  soma = nodes_[maxDiaIndex].elecCompt();
491  }
492  }
493  // Move soma to start of nodes_ vector.
494  if ( maxDiaIndex != 0 )
495  {
496  NeuroNode temp = nodes_[0];
497  nodes_[0] = nodes_[maxDiaIndex];
498  nodes_[maxDiaIndex] = temp;
499  }
500  return soma;
501 }
502 
504  unsigned int parent, unsigned int self,
505  double x, double y, double z )
506 {
507  static const double EPSILON = 1e-8;
508  NeuroNode dummy( nodes_[ self ] );
509  dummy.clearChildren();
510  dummy.setNumDivs( 0 );
511  bool isCylinder = (geometryPolicy_ == "cylinder" );
512  dummy.setIsCylinder( isCylinder );
513  dummy.setX( x );
514  dummy.setY( y );
515  dummy.setZ( z );
516  // Now insert the dummy as a surrogate parent.
517  dummy.setParent( parent );
518  dummy.addChild( self );
519  nodes_[ self ].setParent( nodes_.size() );
520  // Idiot check for a bad dimensioned compartment.
521  if ( nodes_[self].calculateLength( dummy ) < EPSILON )
522  {
523  double length = nodes_[self].getLength();
524  dummy.setX( x - length );
525  assert( doubleEq( nodes_[self].calculateLength( dummy ), length) );
526  }
527  nodes_.push_back( dummy );
528 }
529 
531 {
532  // First deal with the soma, always positioned at node 0.
533  unsigned int num = nodes_.size();
534  for ( unsigned int i = 0; i < num; ++i )
535  {
536  if ( nodes_[i].parent() == ~0U )
537  {
538  Id elec = nodes_[i].elecCompt();
539  double x = Field< double >::get( elec, "x0" );
540  double y = Field< double >::get( elec, "y0" );
541  double z = Field< double >::get( elec, "z0" );
542  insertSingleDummy( ~0U, i, x, y, z );
543  }
544  }
545 
546  // Second pass: insert dummy nodes for children.
547  // Need to know if parent has multiple children, because each of
548  // them will need a dummyNode to connect to.
549  // In all the policies so far, the dummy nodes take the same diameter
550  // as the children that they host.
551  for ( unsigned int i = 0; i < nodes_.size(); ++i )
552  {
553  vector< unsigned int > kids = nodes_[i].children();
554  if ( (!nodes_[i].isDummyNode()) && kids.size() > 1 )
555  {
556  for( unsigned int j = 0; j < kids.size(); ++j )
557  {
558  double x = nodes_[i].getX(); // use coords of parent.
559  double y = nodes_[i].getY();
560  double z = nodes_[i].getZ();
561  insertSingleDummy( i, kids[j], x, y, z );
562  // Replace the old kid entry with the dummy
563  kids[j] = nodes_.size() - 1;
564  }
565  // Connect up the parent to the dummy nodes.
566  nodes_[i].clearChildren();
567  for( unsigned int j = 0; j < kids.size(); ++j )
568  nodes_[i].addChild( kids[j] );
569  }
570  }
571 }
572 
574 {
575  if ( compt.element()->getName().find( "shaft" ) != string::npos ||
576  compt.element()->getName().find( "neck" ) != string::npos )
577  {
578  shaft_.push_back( compt );
579  return true;
580  }
581  if ( compt.element()->getName().find( "spine" ) != string::npos ||
582  compt.element()->getName().find( "head" ) != string::npos )
583  {
584  head_.push_back( compt );
585  return true;
586  }
587  return false;
588 }
589 
590 
592 {
593  spineListOut()->send( e, shaft_, head_, parent_ );
594 
595  vector< double > ret;
596  vector< double > psdCoords;
597  vector< unsigned int > index( head_.size(), 0 );
598  if ( e.element()->hasMsgs( psdListOut()->getBindIndex() ) )
599  {
600  // Later can refine to deal with spineless PSDs.
601  for ( unsigned int i = 0; i < head_.size(); ++i )
602  {
603  SpineEntry se =
604  SpineEntry( shaft_[i], head_[i], parent_[i] );
605  ret = se.psdCoords();
606  assert( ret.size() == 8 );
607  psdCoords.insert( psdCoords.end(), ret.begin(), ret.end() );
608  index[i] = i;
609  }
610  // ids.clear();
611  // e.element()->getNeighbors( ids, psdListOut() );
612  psdListOut()->send( e, psdCoords, head_, index );
613  }
614 }
615 
621 {
622  assert( shaft_.size() == parent_.size() );
623  vector< unsigned int > pa = parent_;
624  for ( unsigned int i = 0; i < shaft_.size(); ++i )
625  {
626  const NeuroNode& nn = nodes_[ pa[i] ];
627  double x0 = Field< double >::get( shaft_[i], "x0" );
628  double y0 = Field< double >::get( shaft_[i], "y0" );
629  double z0 = Field< double >::get( shaft_[i], "z0" );
630  const NeuroNode& pn = nodes_[ nn.parent() ];
631  unsigned int index = 0;
632  double r = nn.nearest( x0, y0, z0, pn, index );
633  if ( r >= 0.0 )
634  {
635  parent_[i] = index + nn.startFid();
636  }
637  else
638  {
639  cout << "Warning: NeuroMesh::updateShaftParents: may be"
640  " misaligned on " << i << ", r=" << r <<
641  "\n pt=(" << x0 << "," << y0 << "," << z0 << ")" <<
642  "pa=(" << nn.getX() << "," << nn.getY() << "," << nn.getZ() << ")" <<
643  "\n";
644  parent_[i] = index + nn.startFid();
645  }
646  }
647 }
648 
649 // Uses all compartments, and if they have spines on them adds those too.
650 void NeuroMesh::setSubTree( const Eref& e, vector< ObjId > compts )
651 {
652  sort( compts.begin(), compts.end() );
653  if ( separateSpines_ )
654  {
657  updateCoords();
659  transmitSpineInfo( e );
660  }
661  else
662  {
663  NeuroNode::buildTree( nodes_, compts );
665  updateCoords();
666  }
667  subTreePath_ = "Undefined: subTree set as a compartment list";
668 }
669 
670 vector< ObjId > NeuroMesh::getSubTree( const Eref& e ) const
671 {
672  vector< Id > temp = getElecComptList();
673  vector< ObjId > ret( temp.size() );
674  for ( unsigned int i = 0; i < ret.size(); ++i )
675  ret[i] = temp[i];
676  return ret;
677 }
678 
679 // Uses all compartments, and if they have spines on them adds those too.
680 void NeuroMesh::setSubTreePath( const Eref& e, string path )
681 {
682  vector< ObjId > compts;
683  wildcardFind( path, compts );
684  setSubTree( e, compts );
685  subTreePath_ = path;
686 }
687 
688 string NeuroMesh::getSubTreePath( const Eref& e ) const
689 {
690  return subTreePath_;
691 }
692 
694 {
695  if ( v != separateSpines_ )
696  {
697  separateSpines_ = v;
698  updateCoords();
699  }
700 }
701 
703 {
704  return separateSpines_;
705 }
706 
707 unsigned int NeuroMesh::getNumSegments() const
708 {
709  unsigned int ret = 0;
710  for ( vector< NeuroNode >::const_iterator i = nodes_.begin();
711  i != nodes_.end(); ++i )
712  ret += !i->isDummyNode();
713  return ret;
714 }
715 
716 unsigned int NeuroMesh::getNumDiffCompts() const
717 {
718  return nodeIndex_.size();
719 }
720 
721 vector< unsigned int > NeuroMesh::getParentVoxel() const
722 {
723  return parentVoxel_;
724 }
725 
726 vector< Id > NeuroMesh::getElecComptMap() const
727 {
728  vector< Id > ret( nodeIndex_.size() );
729  for ( unsigned int i = 0; i < nodeIndex_.size(); ++i )
730  {
731  ret[i] = nodes_[nodeIndex_[i]].elecCompt();
732  // cout << i << " " << nodeIndex_[i] << " " << ret[i] << endl;
733 
734  }
735  return ret;
736 }
737 
738 vector< Id > NeuroMesh::getElecComptList() const
739 {
740  vector< Id > ret;
741  for ( vector< NeuroNode >::const_iterator
742  i = nodes_.begin(); i != nodes_.end(); ++i )
743  {
744  if ( !i->isDummyNode() )
745  ret.push_back( i->elecCompt() );
746  }
747  return ret;
748 }
749 
750 vector< unsigned int > NeuroMesh::getStartVoxelInCompt() const
751 {
752  vector< unsigned int > ret;
753  for ( vector< NeuroNode >::const_iterator
754  i = nodes_.begin(); i != nodes_.end(); ++i )
755  {
756  if ( !i->isDummyNode() )
757  ret.push_back( i->startFid() );
758  }
759  return ret;
760 }
761 
762 vector< unsigned int > NeuroMesh::getEndVoxelInCompt() const
763 {
764  vector< unsigned int > ret;
765  for ( vector< NeuroNode >::const_iterator
766  i = nodes_.begin(); i != nodes_.end(); ++i )
767  {
768  if ( !i->isDummyNode() )
769  ret.push_back( i->startFid() + i->getNumDivs() );
770  }
771  return ret;
772 }
773 
775 {
776  vector< int > ret( nodeIndex_.size(), -1 ); //-1 means no spine present
777  for ( unsigned int i = 0; i < parent_.size(); ++i )
778  {
779  assert( parent_[i] < ret.size() );
780  ret[ parent_[i] ] = i;
781  }
782  return ret;
783 }
784 
785 vector< unsigned int > NeuroMesh::getDendVoxelsOnCompartment(ObjId compt) const
786 {
787  vector< unsigned int > ret;
788  for ( vector< NeuroNode >::const_iterator
789  i = nodes_.begin(); i != nodes_.end(); ++i )
790  {
791  if ( !i->isDummyNode() && i->elecCompt() == compt.id )
792  {
793  for ( unsigned int j = 0; j < i->getNumDivs(); ++j )
794  {
795  ret.push_back( j + i->startFid() );
796  }
797  }
798  }
799  return ret;
800 }
801 
802 vector< unsigned int > NeuroMesh::getSpineVoxelsOnCompartment(ObjId compt) const
803 {
804  vector< unsigned int > ret;
805  assert( shaft_.size() == head_.size() );
806  for ( unsigned int i = 0; i < shaft_.size(); ++i )
807  {
808  if ( shaft_[i] == compt.id || head_[i] == compt.id )
809  ret.push_back(i);
810  }
811  return ret;
812 }
813 
814 const vector< double >& NeuroMesh::vGetVoxelVolume() const
815 {
816  return vs_;
817 }
818 
819 const vector< double >& NeuroMesh::vGetVoxelMidpoint() const
820 {
821  static vector< double > midpoint;
822  unsigned int num = vs_.size();
823  midpoint.resize( num * 3 );
824  vector< double >::iterator k = midpoint.begin();
825  for ( unsigned int i = 0; i < nodes_.size(); ++i )
826  {
827  const NeuroNode& nn = nodes_[i];
828  if ( !nn.isDummyNode() )
829  {
830  assert( nn.parent() < nodes_.size() );
831  const NeuroNode& parent = nodes_[ nn.parent() ];
832  for ( unsigned int j = 0; j < nn.getNumDivs(); ++j )
833  {
834  vector< double > coords = nn.getCoordinates( parent, j );
835  *k = ( coords[0] + coords[3] ) / 2.0;
836  *(k + num ) = ( coords[1] + coords[4] ) / 2.0;
837  *(k + 2 * num ) = ( coords[2] + coords[5] ) / 2.0;
838  k++;
839  }
840  }
841  }
842  return midpoint;
843 }
844 
845 const vector< double >& NeuroMesh::getVoxelArea() const
846 {
847  return area_;
848 }
849 
850 const vector< double >& NeuroMesh::getVoxelLength() const
851 {
852  return length_;
853 }
854 
856 {
857  double ret = 0.0;
858  for ( vector< double >::const_iterator i =
859  vs_.begin(); i != vs_.end(); ++i )
860  ret += *i;
861  return ret;
862 }
863 
864 bool NeuroMesh::vSetVolumeNotRates( double volume )
865 {
866  assert( parentVoxel_.size() == nodeIndex_.size() );
867  assert( parentVoxel_.size() == 1 );
868  assert( vs_.size() == 1 );
869  if ( parentVoxel_.size() > 1 ) // Can't handle multicompartments yet.
870  return false;
871  NeuroNode& n = nodes_[0];
872  double oldvol = n.volume( nodes_[0] );
873  double scale = pow( volume / oldvol, 1.0/3.0 );
874  n.setLength( n.getLength() * scale );
875  n.setDia( n.getDia() * scale );
876  vs_[0] *= volume / oldvol;
877  area_[0] *= scale * scale;
878  length_[0] *= scale;
879  diffLength_ = length_[0];
880 
881  return true;
882 }
883 
885 // FieldElement assignment stuff for MeshEntries
887 
889 unsigned int NeuroMesh::getMeshType( unsigned int fid ) const
890 {
891  assert( fid < nodeIndex_.size() );
892  assert( nodeIndex_[fid] < nodes_.size() );
893  if ( nodes_[ nodeIndex_[fid] ].isSphere() )
894  return SPHERE_SHELL_SEG;
895 
896  return CYL;
897 }
898 
900 unsigned int NeuroMesh::getMeshDimensions( unsigned int fid ) const
901 {
902  return 3;
903 }
904 
906 double NeuroMesh::getMeshEntryVolume( unsigned int fid ) const
907 {
908  if ( nodeIndex_.size() == 0 )
909  return 1.0; // A default value to use before init
910  assert( fid < nodeIndex_.size() );
911  assert( nodeIndex_[fid] < nodes_.size() );
912  const NeuroNode& node = nodes_[ nodeIndex_[fid] ];
913  assert( fid >= node.startFid() );
914  if ( node.parent() == ~0U )
915  return node.voxelVolume( node, fid - node.startFid() );
916  assert ( node.parent() < nodes_.size() );
917  const NeuroNode& parent = nodes_[ node.parent() ];
918  return node.voxelVolume( parent, fid - node.startFid() );
919 }
920 
923 vector< double > NeuroMesh::getCoordinates( unsigned int fid ) const
924 {
925  assert( fid < nodeIndex_.size() );
926  assert( nodeIndex_[fid] < nodes_.size() );
927  const NeuroNode& node = nodes_[ nodeIndex_[fid] ];
928  assert( fid >= node.startFid() );
929  assert ( node.parent() < nodes_.size() );
930  const NeuroNode& parent = nodes_[ node.parent() ];
931 
932  return node.getCoordinates( parent, fid - node.startFid() );
933 }
934 
936 vector< double > NeuroMesh::getDiffusionArea( unsigned int fid ) const
937 {
938  assert( fid < nodeIndex_.size() );
939  assert( nodeIndex_[fid] < nodes_.size() );
940  const NeuroNode& node = nodes_[ nodeIndex_[fid] ];
941  assert( fid >= node.startFid() );
942  assert ( node.parent() < nodes_.size() );
943  const NeuroNode& parent = nodes_[ node.parent() ];
944  vector< double > ret;
945  vector< unsigned int > neighbors = getNeighbors( fid );
946  for ( unsigned int i = 0; i < neighbors.size(); ++i )
947  {
948  ret.push_back( node.getDiffusionArea( parent, neighbors[ i ] ) );
949  }
950  return ret;
951 }
952 
955 // Regular points return vector( 2, 1.0 );
956 vector< double > NeuroMesh::getDiffusionScaling( unsigned int fid ) const
957 {
958  /*
959  if ( nodeIndex_.size() <= 1 )
960  return vector< double >( 0 );
961 
962  if ( !isToroid_ && ( fid == 0 || fid == (nodeIndex_.size() - 1) ) )
963  return vector< double >( 1, 1.0 );
964  */
965 
966  return vector< double >( 2, 1.0 );
967 }
968 
971 double NeuroMesh::extendedMeshEntryVolume( unsigned int fid ) const
972 {
973  if ( fid < nodeIndex_.size() )
974  {
975  return getMeshEntryVolume( fid );
976  }
977  else
978  {
979  return MeshCompt::extendedMeshEntryVolume( fid - nodeIndex_.size() );
980  }
981 }
982 
983 
984 
986 // Dest funcsl
988 
989 #if 0
993  const SrcFinfo2< unsigned int, vector< double > >* meshStatsFinfo
994  )
995 {
996  vector< double > ret( vGetEntireVolume() / nodeIndex_.size() ,1 );
997  meshStatsFinfo->send( e, 1, ret );
998 }
999 #endif
1000 
1002  const Eref& e,
1003  unsigned int numNodes, unsigned int numThreads )
1004 {
1005  /*
1006  unsigned int numEntries = nodeIndex_.size();
1007  vector< double > vols( numEntries, 0.0 );
1008  double oldVol = getMeshEntryVolume( 0 );
1009  for ( unsigned int i = 0; i < numEntries; ++i ) {
1010  assert( nodeIndex_[i] < nodes_.size() );
1011  NeuroNode& node = nodes_[ nodeIndex_[i] ];
1012  assert( nodes_.size() > node.parent() );
1013  NeuroNode& parent = nodes_[ node.parent() ];
1014  vols[i] = node.voxelVolume( parent, i );
1015  }
1016  vector< unsigned int > localEntries( numEntries );
1017  vector< vector< unsigned int > > outgoingEntries;
1018  vector< vector< unsigned int > > incomingEntries;
1019  meshSplit()->send( e,
1020  oldVol,
1021  vols, localEntries,
1022  outgoingEntries, incomingEntries );
1023  */
1024 }
1026 
1030 unsigned int NeuroMesh::innerGetNumEntries() const
1031 {
1032  return nodeIndex_.size();
1033 }
1034 
1040 void NeuroMesh::innerSetNumEntries( unsigned int n )
1041 {
1042  static const unsigned int WayTooLarge = 1000000;
1043  if ( n == 0 || n > WayTooLarge )
1044  {
1045  cout << "Warning: NeuroMesh::innerSetNumEntries( " << n <<
1046  " ): out of range\n";
1047  return;
1048  }
1049  double totalLength = 0;
1050  for ( vector< NeuroNode >::iterator i = nodes_.begin();
1051  i != nodes_.end(); ++i )
1052  {
1053  if ( !i->isDummyNode() )
1054  {
1055  if ( i->isSphere() )
1056  totalLength += i->getDia();
1057  else
1058  totalLength += i->getLength();
1059  }
1060  }
1061  assert( totalLength > 0 );
1062  diffLength_ = totalLength / n;
1063  updateCoords();
1064 }
1065 
1066 
1079  double size, unsigned int numEntries )
1080 {
1081 
1082  if ( size > 10e-3 )
1083  {
1084  cout << "Warning: attempt to build a neuron of dendritic length " <<
1085  size << " metres.\n Seems improbable.\n" <<
1086  "Using default of 0.001 m\n";
1087  size = 1e-3;
1088  }
1089 
1090  diffLength_ = size / numEntries;
1091 
1092  vector< unsigned int > noChildren( 0 );
1093  vector< unsigned int > oneChild( 1, 2 );
1094 
1095  if ( size < 20e-6 )
1096  {
1097  CylBase cb( 0, 0, 0, size, 0, numEntries );
1098  NeuroNode soma( cb, 0, noChildren, 0, Id(), true );
1099  nodes_.resize( 1, soma );
1100  nodeIndex_.resize( 1, 0 );
1101  }
1102  else
1103  {
1104  CylBase cb( 0, 0, 0, 20e-6, 0, 1 );
1105  NeuroNode soma( cb, 0, oneChild, 0, Id(), true );
1106  nodes_.resize( 1, soma );
1107  nodeIndex_.resize( 1, 0 );
1108 
1109  CylBase cbDummy( 0, 0, 10e-6, 4e-6, 0, 0 );
1110  NeuroNode dummy( cbDummy, 0, noChildren, 1, Id(), false );
1111  nodes_.push_back( dummy );
1112 
1113  CylBase cbDend( 0, 0, size, 2e-6, size - 10e-6, numEntries - 1);
1114  NeuroNode dend( cbDend, 1, noChildren, 2, Id(), false );
1115  nodes_.push_back( dend );
1116  for ( unsigned int i = 1; i < numEntries; ++i )
1117  nodeIndex_.push_back( 2 );
1118  }
1119  updateCoords();
1120 }
1121 
1123 // Utility function to set up Stencil for diffusion
1125 
1126 double NeuroMesh::getAdx( unsigned int i, unsigned int& parentFid ) const
1127 {
1128  const NeuroNode &nn = nodes_[ nodeIndex_[i] ];
1129  if ( nn.isDummyNode() || nn.parent() == ~0U )
1130  return -1; // No diffusion, bail out.
1131  const NeuroNode *pa = &nodes_[ nn.parent() ];
1132  double L1 = nn.getLength() / nn.getNumDivs();
1133  double L2 = L1;
1134  parentFid = i - 1;
1135  if ( nn.startFid() == i )
1136  {
1137  // We're at the start of the node, need to refer to parent for L
1138  const NeuroNode* realParent = pa;
1139  if ( pa->isDummyNode() )
1140  {
1141  if ( pa->parent() == ~0U )
1142  {
1143  parentFid = -1;
1144  return -1; // No diffusion, bail out.
1145  }
1146  assert( pa->parent() < nodes_.size() );
1147  realParent = &nodes_[ realParent->parent() ];
1148  if ( realParent->isDummyNode() )
1149  {
1150  // Still dummy. So we're at a terminus. No diffusion
1151  return -1;
1152  }
1153  }
1154  L2 = realParent->getLength() / realParent->getNumDivs();
1155  parentFid = realParent->startFid() +
1156  realParent->getNumDivs() - 1;
1157  }
1158  assert( parentFid < nodeIndex_.size() );
1159  double length = 0.5 * (L1 + L2 );
1160  // Note that we use the parent node here even if it is a dummy.
1161  // It has the correct diameter.
1162  double adx = nn.getDiffusionArea( *pa, i - nn.startFid() ) / length;
1163  return adx;
1164 }
1165 
1167 {
1168  parentVoxel_.clear();
1169  setStencilSize( nodeIndex_.size(), nodeIndex_.size() );
1170  SparseMatrix< double > sm( nodeIndex_.size(), nodeIndex_.size() );
1171  vector< vector< double > > paEntry( nodeIndex_.size() );
1172  vector< vector< unsigned int > > paColIndex( nodeIndex_.size() );
1173  // It is very easy to set up the matrix using the parent as there is
1174  // only one parent for every voxel.
1175  for ( unsigned int i = 0; i < nodeIndex_.size(); ++i )
1176  {
1177  unsigned int parentFid;
1178  double adx = getAdx( i, parentFid );
1179  parentVoxel_.push_back( parentFid );
1180  if ( adx < 0.0 ) // No diffusion, so don't put in any entry.
1181  continue;
1182  /*
1183  const NeuroNode &nn = nodes_[ nodeIndex_[i] ];
1184  const NeuroNode *pa = &nodes_[ nn.parent() ];
1185  double L1 = nn.getLength() / nn.getNumDivs();
1186  double L2 = L1;
1187  unsigned int parentFid = i - 1;
1188  if ( nn.startFid() == i ) {
1189  // We're at the start of the node, need to refer to parent for L
1190  const NeuroNode* realParent = pa;
1191  if ( pa->isDummyNode() ) {
1192  realParent = &nodes_[ realParent->parent() ];
1193  if ( realParent->isDummyNode() ) {
1194  // Still dummy. So we're at a terminus. No diffusion
1195  continue;
1196  }
1197  }
1198  L2 = realParent->getLength() / realParent->getNumDivs();
1199  parentFid = realParent->startFid() +
1200  realParent->getNumDivs() - 1;
1201  }
1202  assert( parentFid < nodeIndex_.size() );
1203  double length = 0.5 * (L1 + L2 );
1204  // Note that we use the parent node here even if it is a dummy.
1205  // It has the correct diameter.
1206  double adx = nn.getDiffusionArea( *pa, i - nn.startFid() ) / length;
1207  */
1208  paEntry[ i ].push_back( adx );
1209  paColIndex[ i ].push_back( parentFid );
1210  // Now put in the symmetric entries.
1211  paEntry[ parentFid ].push_back( adx );
1212  paColIndex[ parentFid ].push_back( i );
1213  }
1214 
1215  // Now go through the paEntry and paColIndex and build sparse matrix.
1216  // We have to do this separately because the sparse matrix has to be
1217  // build up in row order, and sorted, whereas the entries above
1218  // are random access.
1219  for ( unsigned int i = 0; i < nodeIndex_.size(); ++i )
1220  {
1221  unsigned int num = paColIndex[i].size();
1222  vector< Ecol > e( num );
1223  vector< double > entry( num );
1224  vector< unsigned int > colIndex( num );
1225  for ( unsigned int j = 0; j < num; ++j )
1226  {
1227  e[j] = Ecol( paEntry[i][j], paColIndex[i][j] );
1228  }
1229  sort( e.begin(), e.end() );
1230 
1231  for ( unsigned int j = 0; j < num; ++j )
1232  {
1233  entry[j] = e[j].e_;
1234  colIndex[j] = e[j].col_;
1235  }
1236  addRow( i, entry, colIndex );
1237  }
1239 }
1240 
1241 
1242 const vector< NeuroNode >& NeuroMesh::getNodes() const
1243 {
1244  return nodes_;
1245 }
1246 
1248 // Utility function for junctions
1250 
1252  vector< VoxelJunction >& ret ) const
1253 {
1254  const CubeMesh* cm = dynamic_cast< const CubeMesh* >( other );
1255  if ( cm )
1256  {
1257  matchCubeMeshEntries( other, ret );
1258  return;
1259  }
1260  const EndoMesh* em = dynamic_cast< const EndoMesh* >( other );
1261  if ( em )
1262  {
1263  em->matchMeshEntries( this, ret );
1264  flipRet( ret );
1265  return;
1266  }
1267  const SpineMesh* sm = dynamic_cast< const SpineMesh* >( other );
1268  if ( sm )
1269  {
1270  sm->matchNeuroMeshEntries( this, ret );
1271  flipRet( ret );
1272  return;
1273  }
1274  const NeuroMesh* nm = dynamic_cast< const NeuroMesh* >( other );
1275  if ( nm )
1276  {
1277  matchNeuroMeshEntries( other, ret );
1278  return;
1279  }
1280  cout << "Warning: NeuroMesh::matchMeshEntries: unknown class\n";
1281 }
1282 
1283 void NeuroMesh::indexToSpace( unsigned int index,
1284  double& x, double& y, double& z ) const
1285 {
1286  if ( index >= innerGetNumEntries() )
1287  return;
1288  const NeuroNode& nn = nodes_[ nodeIndex_[ index ] ];
1289  const NeuroNode& pa = nodes_[ nn.parent() ];
1290  Vec a( pa.getX(), pa.getY(), pa.getZ() );
1291  Vec b( nn.getX(), nn.getY(), nn.getZ() );
1292  double frac = ( ( index - nn.startFid() ) + 0.5 ) / nn.getNumDivs();
1293  Vec pt = a.pointOnLine( b, frac );
1294  x = pt.a0();
1295  y = pt.a1();
1296  z = pt.a2();
1297 }
1298 
1299 double NeuroMesh::nearest( double x, double y, double z,
1300  unsigned int& index ) const
1301 {
1302  double best = 1e12;
1303  index = 0;
1304  for( unsigned int i = 0; i < nodes_.size(); ++i )
1305  {
1306  const NeuroNode& nn = nodes_[i];
1307  if ( !nn.isDummyNode() )
1308  {
1309  assert( nn.parent() < nodes_.size() );
1310  const NeuroNode& pa = nodes_[ nn.parent() ];
1311  double linePos;
1312  double r;
1313  double near = nn.nearest( x, y, z, pa, linePos, r );
1314  if ( linePos >= 0 && linePos < 1.0 )
1315  {
1316  if ( best > near )
1317  {
1318  best = near;
1319  index = linePos * nn.getNumDivs() + nn.startFid();
1320  }
1321  }
1322  }
1323  }
1324  if ( best == 1e12 )
1325  return -1;
1326  return best;
1327 }
1328 
1330  vector< VoxelJunction >& ret ) const
1331 {
1332  for( unsigned int i = 0; i < nodes_.size(); ++i )
1333  {
1334  const NeuroNode& nn = nodes_[i];
1335  if ( !nn.isDummyNode() )
1336  {
1337  assert( nn.parent() < nodes_.size() );
1338  const NeuroNode& pa = nodes_[ nn.parent() ];
1339  nn.matchCubeMeshEntries( other, pa, nn.startFid(),
1340  surfaceGranularity_, ret, true, false );
1341  }
1342  }
1343 }
1344 
1346  vector< VoxelJunction >& ret ) const
1347 {
1348 }
static const Cinfo * initCinfo()
Definition: ChemCompt.cpp:25
int wildcardFind(const string &path, vector< ObjId > &ret)
Definition: Wildcard.cpp:169
vector< double > getDiffusionScaling(unsigned int fid) const
Virtual function to return scale factor for diffusion. 1 here.
Definition: NeuroMesh.cpp:956
const vector< double > & vGetVoxelVolume() const
Virtual func so that derived classes can pass voxel volume back.
Definition: NeuroMesh.cpp:814
vector< Id > head_
Id of shaft compartment.
Definition: NeuroMesh.h:330
double getMeshEntryVolume(unsigned int fid) const
Virtual function to return volume of mesh Entry.
Definition: NeuroMesh.cpp:906
double getLength() const
Definition: CylBase.cpp:98
double a0() const
Definition: Vec.h:34
void setNumDivs(unsigned int v)
Definition: CylBase.cpp:103
void setDiffLength(double v)
Definition: NeuroMesh.cpp:399
vector< Id > shaft_
Definition: NeuroMesh.h:329
static void buildSpinyTree(vector< ObjId > &elist, vector< NeuroNode > &nodes, vector< Id > &shaftId, vector< Id > &headId, vector< unsigned int > &spineParent)
Definition: NeuroNode.cpp:491
void innerResetStencil()
virtual func implemented here.
Definition: MeshCompt.cpp:49
vector< int > getSpineVoxelOnDendVoxel() const
Definition: NeuroMesh.cpp:774
const double NA
Definition: consts.cpp:15
void setParent(unsigned int parent)
Definition: NeuroNode.cpp:111
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
void insertDummyNodes()
Definition: NeuroMesh.cpp:530
vector< unsigned int > getNeighbors(unsigned int fid) const
Looks up stencil to return vector of indices of coupled voxels.
Definition: MeshCompt.cpp:69
void matchCubeMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: NeuroMesh.cpp:1329
void setX(double v)
Definition: CylBase.cpp:53
bool separateSpines_
Max permitted length constant for diffusion.
Definition: NeuroMesh.h:314
Id getParentFromMsg(Id id)
Definition: NeuroMesh.cpp:459
Definition: Dinfo.h:60
void addRow(unsigned int index, const vector< double > &entry, const vector< unsigned int > &colIndex)
Definition: MeshCompt.cpp:98
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
void indexToSpace(unsigned int index, double &x, double &y, double &z) const
Definition: NeuroMesh.cpp:1283
Id tryParent(Id id, const string &msgName)
Definition: NeuroMesh.cpp:446
double getX() const
Definition: CylBase.cpp:58
static void buildTree(vector< NeuroNode > &nodes, vector< ObjId > elist)
Definition: NeuroNode.cpp:558
void setGeometryPolicy(string v)
Definition: NeuroMesh.cpp:410
Id id
Definition: ObjId.h:98
int strncasecmp(const string &a, const string &b, size_t n)
Compares the two strings a and b for first n characters, ignoring the case of the characters...
Definition: strutil.cpp:148
double getDiffLength() const
Definition: NeuroMesh.cpp:405
double extendedMeshEntryVolume(unsigned int fid) const
Virtual function to return volume of mesh Entry, including.
Definition: MeshCompt.cpp:36
vector< unsigned int > getEndVoxelInCompt() const
Definition: NeuroMesh.cpp:762
vector< double > getCoordinates(unsigned int fid) const
Virtual function to return coords of mesh Entry.
Definition: NeuroMesh.cpp:923
unsigned int getMeshType(unsigned int fid) const
Virtual function to return MeshType of specified entry.
Definition: NeuroMesh.cpp:889
double voxelVolume(const CylBase &parent, unsigned int fid) const
Definition: CylBase.cpp:152
vector< Id > getElecComptMap() const
Definition: NeuroMesh.cpp:726
double a2() const
Definition: Vec.h:40
Definition: ObjId.h:20
unsigned int getMeshDimensions(unsigned int fid) const
Virtual function to return dimensions of specified entry.
Definition: NeuroMesh.cpp:900
unsigned int getNumDiffCompts() const
Definition: NeuroMesh.cpp:716
const int numEntries
Definition: proc.cpp:60
vector< unsigned int > getStartVoxelInCompt() const
Definition: NeuroMesh.cpp:750
unsigned int innerGetDimensions() const
Definition: NeuroMesh.cpp:441
double getDiffusionArea(const CylBase &parent, unsigned int index) const
Definition: CylBase.cpp:210
Element * element() const
Definition: Eref.h:42
unsigned int startFid() const
Definition: NeuroNode.cpp:74
double volume(const CylBase &parent) const
Returns vol of current node. Usually needs to refer to parent.
Definition: CylBase.cpp:135
void setLength(double v)
Definition: CylBase.cpp:93
const vector< double > & getVoxelArea() const
Definition: NeuroMesh.cpp:845
double getY() const
Definition: CylBase.cpp:68
vector< unsigned int > getSpineVoxelsOnCompartment(ObjId compt) const
Definition: NeuroMesh.cpp:802
vector< double > vs_
Definition: NeuroMesh.h:294
vector< double > getDiffusionArea(unsigned int fid) const
Virtual function to return diffusion X-section area.
Definition: NeuroMesh.cpp:936
vector< double > getCoordinates(const CylBase &parent, unsigned int entry) const
Definition: CylBase.cpp:172
double nearest(double x, double y, double z, const CylBase &parent, double &linePos, double &r) const
Definition: CylBase.cpp:378
void transmitSpineInfo(const Eref &e)
Definition: NeuroMesh.cpp:591
vector< unsigned int > getDendVoxelsOnCompartment(ObjId compt) const
Definition: NeuroMesh.cpp:785
vector< Id > getElecComptList() const
Definition: NeuroMesh.cpp:738
string getSubTreePath(const Eref &e) const
Definition: NeuroMesh.cpp:688
vector< ObjId > getSubTree(const Eref &e) const
Definition: NeuroMesh.cpp:670
const vector< double > & getVoxelLength() const
Definition: NeuroMesh.cpp:850
bool doubleEq(double x, double y)
Definition: doubleEq.cpp:16
const vector< double > & vGetVoxelMidpoint() const
Virtual func so that derived classes can return voxel midpoint.
Definition: NeuroMesh.cpp:819
Definition: Vec.h:13
void updateCoords()
Definition: NeuroMesh.cpp:343
bool hasMsgs(BindIndex b) const
Definition: Element.cpp:307
void innerHandleNodeInfo(const Eref &e, unsigned int numNodes, unsigned int numThreads)
Definition: NeuroMesh.cpp:1001
Definition: MeshEntry.h:20
vector< double > psdCoords() const
Definition: SpineEntry.cpp:188
NeuroMesh & operator=(const NeuroMesh &other)
Definition: NeuroMesh.cpp:316
vector< unsigned int > getParentVoxel() const
Definition: NeuroMesh.cpp:721
void setSeparateSpines(bool v)
Definition: NeuroMesh.cpp:693
void matchCubeMeshEntries(const ChemCompt *other, const CylBase &parent, unsigned int startIndex, double granularity, vector< VoxelJunction > &ret, bool useCylinderCurve, bool useCylinderCap) const
Definition: CylBase.cpp:320
vector< double > length_
Pre-calculation of length of each MeshEntry.
Definition: NeuroMesh.h:303
void setZ(double v)
Definition: CylBase.cpp:73
static SrcFinfo3< vector< Id >, vector< Id >, vector< unsigned int > > * spineListOut()
Definition: NeuroMesh.cpp:32
double getMiddleArea(const CylBase &parent, unsigned int index) const
Return cross-section area of middle of specified voxel.
Definition: CylBase.cpp:223
Definition: Eref.h:26
void innerHandleRequestMeshStats(const Eref &e, const SrcFinfo2< unsigned int, vector< double > > *meshStatsFinfo)
bool vSetVolumeNotRates(double volume)
Definition: NeuroMesh.cpp:864
void insertSingleDummy(unsigned int parent, unsigned int self, double x, double y, double z)
Definition: NeuroMesh.cpp:503
double extendedMeshEntryVolume(unsigned int fid) const
Vol of all mesh Entries including abutting diff-coupled voxels.
Definition: NeuroMesh.cpp:971
static const Cinfo * neuroMeshCinfo
Definition: NeuroMesh.cpp:282
void updateShaftParents()
Definition: NeuroMesh.cpp:620
void setIsCylinder(bool v)
Definition: CylBase.cpp:113
void setY(double v)
Definition: CylBase.cpp:63
void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: NeuroMesh.cpp:1251
unsigned int getNumSegments() const
Definition: NeuroMesh.cpp:707
double getDia() const
Definition: CylBase.cpp:88
void innerBuildDefaultMesh(const Eref &e, double size, unsigned int numEntries)
Virtual func to make a mesh with specified size and numEntries.
Definition: NeuroMesh.cpp:1078
static unsigned int numNodes
double diffLength_
Definition: NeuroMesh.h:306
static char name[]
Definition: mfield.cpp:401
void setSubTree(const Eref &e, vector< ObjId > compartments)
Definition: NeuroMesh.cpp:650
string geometryPolicy_
Definition: NeuroMesh.h:316
void matchNeuroMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: SpineMesh.cpp:543
double getZ() const
Definition: CylBase.cpp:78
vector< unsigned int > parentVoxel_
Index of parent voxel of spines.
Definition: NeuroMesh.h:336
const vector< NeuroNode > & getNodes() const
Definition: NeuroMesh.cpp:1242
void setDia(double v)
Definition: CylBase.cpp:83
double vGetEntireVolume() const
Definition: NeuroMesh.cpp:855
unsigned int parent() const
Definition: NeuroNode.cpp:69
vector< unsigned int > parent_
Id of head compartment.
Definition: NeuroMesh.h:331
bool isDummyNode() const
Definition: NeuroNode.cpp:83
Definition: Id.h:17
unsigned int innerGetNumEntries() const
Definition: NeuroMesh.cpp:1030
double nearest(double x, double y, double z, unsigned int &index) const
Definition: NeuroMesh.cpp:1299
void setSubTreePath(const Eref &e, string path)
Definition: NeuroMesh.cpp:680
double surfaceGranularity_
Definition: NeuroMesh.h:323
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
void setStencilSize(unsigned int numRows, unsigned int numCols)
Definition: MeshCompt.cpp:106
double a1() const
Definition: Vec.h:37
unsigned int getNumDivs() const
Definition: CylBase.cpp:108
Id putSomaAtStart(Id origSoma, unsigned int maxDiaIndex)
This shuffles the nodes_ vector to put soma node at the start.
Definition: NeuroMesh.cpp:468
void flipRet(vector< VoxelJunction > &ret) const
Utility function for swapping first and second in VoxelJunctions.
Definition: ChemCompt.cpp:406
#define EPSILON
Definition: MatrixOps.h:28
void buildStencil()
Utility function to set up Stencil for diffusion in NeuroMesh.
Definition: NeuroMesh.cpp:1166
void matchNeuroMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: NeuroMesh.cpp:1345
void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: EndoMesh.cpp:420
static const Cinfo * initCinfo()
Definition: NeuroMesh.cpp:66
const string & getName() const
Definition: Element.cpp:56
string getGeometryPolicy() const
Definition: NeuroMesh.cpp:436
static SrcFinfo3< vector< double >, vector< Id >, vector< unsigned int > > * psdListOut()
Definition: NeuroMesh.cpp:48
double getVoxelLength() const
Return length of voxel. All are equal.
Definition: CylBase.cpp:235
string subTreePath_
Definition: NeuroMesh.h:277
Definition: Cinfo.h:18
static char path[]
Definition: mfield.cpp:403
bool filterSpines(Id compt)
Definition: NeuroMesh.cpp:573
Definition: MeshCompt.h:89
vector< NeuroNode > nodes_
Definition: NeuroMesh.h:270
void innerSetNumEntries(unsigned int n)
Inherited virtual func.
Definition: NeuroMesh.cpp:1040
double getAdx(unsigned int curr, unsigned int &parentFid) const
Definition: NeuroMesh.cpp:1126
bool getSeparateSpines() const
Definition: NeuroMesh.cpp:702
vector< unsigned int > nodeIndex_
Definition: NeuroMesh.h:287
vector< double > area_
Definition: NeuroMesh.h:300
Vec pointOnLine(const Vec &end, double k)
Definition: Vec.cpp:53
void clearChildren()
Definition: NeuroNode.cpp:106
Definition: Finfo.h:12
void addChild(unsigned int child)
Definition: NeuroNode.cpp:101