18 #include "../utility/Vec.h"
19 #include "../utility/strutil.h"
29 unsigned int parent,
const vector< unsigned int >& children,
30 unsigned int startFid,
Id elecCompt,
bool isSphere
35 children_( children ),
36 startFid_( startFid ),
37 elecCompt_( elecCompt ),
45 elecCompt_( elecCompt ),
123 if ( &parent ==
this )
128 double ret = sqrt( dx * dx + dy * dy + dz * dz );
162 assert( proximalOut );
163 assert( cylinderOut );
164 assert( sumRaxialOut );
168 if ( cinfo->
isA(
"SymCompartment" ) ) {
171 all.insert( all.end(), ret.begin(), ret.end() );
173 all.insert( all.end(), ret.begin(), ret.end() );
175 all.insert( all.end(), ret.begin(), ret.end() );
177 all.insert( all.end(), ret.begin(), ret.end() );
180 assert( cinfo->
isA(
"CompartmentBase" ) );
183 all.insert( all.end(), ret.begin(), ret.end() );
185 all.insert( all.end(), ret.begin(), ret.end() );
187 sort( all.begin(), all.end() );
188 all.erase( unique( all.begin(), all.end() ), all.end() );
199 const map< Id, unsigned int >& nodeMap,
200 const vector< NeuroNode >& nodes )
208 for (
unsigned int i = 0; i < all.size(); ++i ) {
209 map< Id, unsigned int >::const_iterator k = nodeMap.find( all[i] );
210 if ( k != nodeMap.end() ) {
213 cout <<
"Warning: NeuroNode::findConnectedCompartments: could not find compartment " << all[i].path() << endl;
228 vector< NeuroNode >& nodes )
230 vector< NeuroNode > temp;
231 vector< unsigned int > nodeMap( nodes.size() );
234 for (
unsigned int i = 0; i < nodes.size(); ++i ) {
236 temp.push_back( nodes[i] );
243 for (
unsigned int i = 0; i < temp.size(); ++i ) {
244 vector< unsigned int >& c = temp[i].children_;
245 for ( vector< unsigned int >::iterator
246 j = c.begin(); j != c.end(); ++j ) {
247 assert( nodeMap[ *j ] != ~0U );
251 unsigned int numRemoved = nodes.size() - temp.size();
273 unsigned int somaIndex = ~0;
274 for (
unsigned int i = 0; i < nodes.size(); ++i ) {
275 const char*
name = nodes[i].elecCompt_.element()->getName().c_str();
277 if ( maxDia < nodes[i].
getDia() ) {
278 maxDia = nodes[i].getDia();
283 if ( somaIndex == ~0U ) {
284 for (
unsigned int i =0; i < nodes.size(); ++i ) {
285 if ( maxDia < nodes[i].
getDia() ) {
286 maxDia = nodes[i].getDia();
291 assert( somaIndex != ~0U );
299 const vector< NeuroNode >& nodes )
301 map< Id , const NeuroNode* > m;
302 for ( vector< NeuroNode >::const_iterator
303 i = tree.begin(); i != tree.end(); ++i ) {
304 m[ i->elecCompt() ] = &( *i );
307 for ( vector< NeuroNode >::const_iterator
308 i = nodes.begin(); i != nodes.end(); ++i ) {
309 if ( m.find( i->elecCompt() ) == m.end() ) {
311 if ( i->parent() != ~0U && i->parent() < nodes.size() )
312 pa = nodes[ i->parent() ].elecCompt();
313 cout <<
"diagnoseTree:" << j++ <<
" " << i->elecCompt().path() <<
314 ", pa = " << i->parent() <<
", " << pa.
path() << endl;
334 vector< unsigned int > seen( nodes.size(), ~0 );
335 vector< NeuroNode > tree;
336 tree.reserve( nodes.size() );
338 tree.push_back( nodes[ start ] );
339 tree.back().parent_ = ~0;
340 nodes[start].innerTraverse( tree, nodes, seen );
342 if ( tree.size() < nodes.size() ) {
343 cout <<
"Warning: NeuroNode::traverse() unable to traverse all nodes:\n";
344 cout <<
"Traversed= " << tree.size() <<
" < total numNodes = " << nodes.size() << endl;
345 cout <<
"This situation may arise if the CellPortion has disjoint compartments\n";
352 vector< NeuroNode >& tree,
353 const vector< NeuroNode >& nodes,
354 vector< unsigned int >& seen
357 unsigned int pa = tree.size() - 1;
358 tree.back().children_.clear();
360 for ( vector< unsigned int >::const_iterator i =
362 assert( *i < nodes.size() );
365 if ( seen[ *i ] == ~0U ) {
366 seen[ *i ] = tree.size();
367 tree[pa].children_.push_back( tree.size() );
368 tree.push_back( nodes[ *i ] );
369 tree.back().parent_ = pa;
370 nodes[*i].innerTraverse( tree, nodes, seen );
373 assert( tree.size() <= nodes.size() );
380 if ( name.find(
"shaft" ) == string::npos &&
381 name.find(
"neck" ) == string::npos &&
382 name.find(
"spine" ) == string::npos &&
383 name.find(
"head" ) == string::npos )
392 vector< Id >& shaftId, vector< Id >& headId,
393 vector< unsigned int >& spineParent )
396 if ( name.find(
"shaft" ) != string::npos ||
397 name.find(
"neck" ) != string::npos ) {
398 spineParent.push_back( dendIndex );
399 shaftId.push_back( compt );
401 bool foundHead =
false;
402 for ( vector< Id >::iterator i =
403 conn.begin(); i != conn.end(); ++i ) {
404 const string& n2 = i->element()->getName();
405 if ( n2.find(
"spine" ) != string::npos ||
406 n2.find(
"head" ) != string::npos ) {
407 headId.push_back( *i );
413 headId.push_back(
Id() );
430 vector< Id >& dend,
const unordered_map< Id, unsigned int >& dendMap,
431 vector< int >& seen,
unsigned int numSeen,
432 vector< Id >& shaftId, vector< Id >& headId,
433 vector< int >& dendParent, vector< unsigned int >& spineParent
437 seen[ dendIndex ] = numSeen;
438 for ( vector< Id >::iterator i = conn.begin(); i != conn.end(); ++i ) {
439 unordered_map< Id, unsigned int >::const_iterator idLookup =
441 if ( idLookup != dendMap.end() ) {
442 if ( !seen[ idLookup->second ] ) {
443 dendParent[ idLookup->second ] = dendIndex;
446 shaftId, headId, dendParent, spineParent );
449 checkForSpine( dendIndex, *i, shaftId, headId, spineParent );
458 vector< unsigned int >& spineParent )
460 size_t sortedIndex(0);
461 vector<int> y(shaftId.size());
462 generate(begin(y), end(y), [&]{
return sortedIndex++; });
463 sort( begin(y), end(y),
464 [&](
int i1,
int i2) {
return shaftId[i1] < shaftId[i2]; } );
466 assert( sortedIndex == shaftId.size() );
467 assert( sortedIndex == headId.size() );
468 assert( sortedIndex == spineParent.size() );
472 auto c = spineParent;
473 for (
size_t i = 0; i < sortedIndex; ++i) {
474 shaftId[i] = a[y[i]];
476 spineParent[i] = c[y[i]];
492 vector< ObjId >& elist, vector< NeuroNode >& nodes,
493 vector< Id >& shaftId, vector< Id >& headId,
494 vector< unsigned int >& spineParent )
497 sort( elist.begin(), elist.end() );
498 unordered_map< Id, unsigned int > dendMap;
500 for ( vector< ObjId >::iterator
501 i = elist.begin(); i != elist.end(); ++i ) {
503 dendMap[ *i ] = dend.size();
505 dend.push_back( *i );
508 vector< int > seen( dend.size(), 0 );
509 vector< int > dendParent( dend.size(), -1 );
511 for (
unsigned int i = 0; i < dend.size(); ++i ) {
515 dendParent, spineParent );
522 for (
unsigned int i = 0; i < dend.size(); ++i )
524 for (
unsigned int i = 0; i < dend.size(); ++i )
528 cout <<
"Warning: NeuroNode::buildSpinyTree: There are " <<
529 numSeen <<
" distinct subgroups on the given path\n";
534 vector< NeuroNode >& nodes,
const unordered_map< Id, unsigned int >& dendMap )
536 if (dendParent < 0 || static_cast< unsigned int >(dendParent) >= nodes.size() )
539 const unordered_map< Id, unsigned int >::const_iterator dendLookup =
541 if ( dendLookup != dendMap.end() ) {
542 assert( dendLookup->second < nodes.size() );
543 nodes[ dendLookup->second ].addChild( index );
559 vector< NeuroNode >& nodes, vector< ObjId > elist )
562 map< Id, unsigned int > nodeMap;
563 for ( vector< ObjId >::iterator
564 i = elist.begin(); i != elist.end(); ++i ) {
565 if ( i->element()->cinfo()->isA(
"CompartmentBase" ) )
568 if ( nodes.size() <= 1 )
570 for (
unsigned int i = 0; i < nodes.size(); ++i ) {
571 if ( nodeMap.find( nodes[i].elecCompt() ) != nodeMap.end() ) {
572 cout <<
"Warning: NeuroNode.buildTree(): Node[" << i <<
573 "] refers to existing compartment: " <<
574 nodes[i].elecCompt().path() << endl;
576 nodeMap[ nodes[i].elecCompt() ] = i;
578 assert( nodeMap.size() == nodes.size() );
579 for (
unsigned int i = 0; i < nodes.size(); ++i )
582 if ( numRemoved > 0 ) {
583 cout <<
"Warning: NeuroNode::buildTree: Removed " <<
584 numRemoved <<
" nodes because they were not connected\n";
592 const vector< unsigned int >& nodeToTempMap )
594 for ( vector< NeuroNode >::iterator
595 i = temp.begin(); i != temp.end(); ++i ) {
596 unsigned int pa = i->parent();
598 assert( nodeToTempMap[ pa ] != ~0U );
599 i->setParent( nodeToTempMap[ pa ] );
602 vector< unsigned int > kids = i->children();
604 for (
unsigned int j = 0; j < kids.size(); ++j ) {
605 unsigned int newKid = nodeToTempMap[ kids[j] ];
607 i->addChild( newKid );
621 vector< Id >& shaftId, vector< Id >& headId,
622 vector< unsigned int >& parent )
627 vector< NeuroNode > temp;
628 temp.reserve( nodes.size() );
629 vector< unsigned int > nodeToTempMap( nodes.size(), ~0U );
630 vector< unsigned int > shaft;
631 vector< unsigned int > reverseShaft( nodes.size(), ~0U );
632 vector< unsigned int > head;
633 for (
unsigned int i = 0; i < nodes.size(); ++i ) {
636 for ( string::iterator j = name.begin(); j != name.end(); ++j )
639 if ( name.find(
"shaft" ) != string::npos ||
640 name.find(
"neck" ) != string::npos ) {
641 reverseShaft[i] = shaft.size();
642 shaft.push_back( i );
644 }
else if ( name.find(
"spine" ) != string::npos ||
645 name.find(
"head" ) != string::npos ) {
649 nodeToTempMap[i] = temp.size();
674 for (
unsigned int i = 0; i < head.size(); ++i ) {
677 assert( reverseShaft[ n.
parent() ] != ~0U );
679 shaftId.push_back( pa.elecCompt() );
680 assert( nodeToTempMap[ pa.parent() ] != ~0U );
681 parent.push_back( nodeToTempMap[ pa.parent() ] );
683 assert( shaftId.size() == headId.size() );
static SrcFinfo2< double, double > * cylinderOut()
static SrcFinfo2< double, double > * proximalOut()
bool isPartOfDend(ObjId i)
static void buildSpinyTree(vector< ObjId > &elist, vector< NeuroNode > &nodes, vector< Id > &shaftId, vector< Id > &headId, vector< unsigned int > &spineParent)
void setParent(unsigned int parent)
Element * element() const
Synonym for Id::operator()()
std::string path(const std::string &separator="/") const
static void traverse(vector< NeuroNode > &nodes, unsigned int start)
static void filterSpines(vector< NeuroNode > &nodes, vector< Id > &shaftId, vector< Id > &headId, vector< unsigned int > &parent)
static void buildTree(vector< NeuroNode > &nodes, vector< ObjId > elist)
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...
static const Cinfo * find(const std::string &name)
const SrcFinfo2< double, double > * raxialOut
static void spinyTraverse(unsigned int dendIndex, vector< Id > &dend, const unordered_map< Id, unsigned int > &dendMap, vector< int > &seen, unsigned int numSeen, vector< Id > &shaftId, vector< Id > &headId, vector< int > &dendParent, vector< unsigned int > &spineParent)
static unsigned int findStartNode(const vector< NeuroNode > &nodes)
unsigned int startFid() const
void diagnoseTree(const vector< NeuroNode > &tree, const vector< NeuroNode > &nodes)
void reassignNodeIndices(vector< NeuroNode > &temp, const vector< unsigned int > &nodeToTempMap)
static void sortByShaftIds(vector< Id > &shaftId, vector< Id > &headId, vector< unsigned int > &spineParent)
const vector< unsigned int > & children() const
static bool checkForSpine(unsigned int dendIndex, Id compt, vector< Id > &shaftId, vector< Id > &headId, vector< unsigned int > &spineParent)
void innerTraverse(vector< NeuroNode > &tree, const vector< NeuroNode > &nodes, vector< unsigned int > &seen) const
bool isA(const string &ancestor) const
const Cinfo * cinfo() const
static SrcFinfo2< double, double > * distalOut()
double calculateLength(const CylBase &parent)
Element * element() const
Id elecCompt_
Id of electrical compartment in which this diffusive compt lives.
unsigned int parent() const
void findConnectedCompartments(const map< Id, unsigned int > &nodeMap, const vector< NeuroNode > &nodes)
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
static vector< Id > findAllConnectedCompartments(Id compt)
const SrcFinfo1< double > * axialOut
static A get(const ObjId &dest, const string &field)
unsigned int getNumDivs() const
void setStartFid(unsigned int f)
const string & getName() const
void setParentAndChildren(unsigned int index, int dendParent, vector< NeuroNode > &nodes, const unordered_map< Id, unsigned int > &dendMap)
static unsigned int removeDisconnectedNodes(vector< NeuroNode > &nodes)
vector< unsigned int > children_
const Finfo * findFinfo(const string &name) const
static SrcFinfo1< double > * sumRaxialOut()
void addChild(unsigned int child)