MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ReadSwc.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) 2003-2015 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 "header.h"
11 #include "../shell/Shell.h"
12 #include "../utility/Vec.h"
13 #include "SwcSegment.h"
14 #include "ReadSwc.h"
15 #include "CompartmentBase.h"
16 #include "Compartment.h"
17 #include "SymCompartment.h"
18 #include <fstream>
19 
20 // Minimum allowed radius of segment, in microns
21 // Believe it or not, some otherwise reasonable files do have smaller radii
22 static const double MinRadius = 0.04;
23 
24 ReadSwc::ReadSwc( const string& fname )
25 {
26  ifstream fin( fname.c_str() );
27  if ( !fin ) {
28  cerr << "ReadSwc:: could not open file " << fname << endl;
29  return;
30  }
31 
32  string temp;
33  int badSegs = 0;
34  while( getline( fin, temp ) ) {
35  if ( temp.length() == 0 )
36  continue;
37  string::size_type pos = temp.find_first_not_of( "\t " );
38  if ( pos == string::npos )
39  continue;
40  if ( temp[pos] == '#' )
41  continue;
42 
43  SwcSegment t( temp );
44  if ( t.OK() )
45  segs_.push_back( SwcSegment( temp ) );
46  else
47  badSegs++;
48  }
49  bool valid = validate();
50  if ( valid ) {
51  assignKids();
53  parseBranches();
54  }
55  cout << "ReadSwc: " << fname << " : NumSegs = " << segs_.size() <<
56  ", bad = " << badSegs <<
57  ", Validated = " << valid <<
58  ", numBranches = " << branches_.size() <<
59  endl;
60  diagnostics();
61 }
62 
63 bool ReadSwc::validate() const
64 {
65  int numStart = 0;
66  int numOrphans = 0;
67  int badIndex = 0;
68  int badRadius = 0;
69  for ( unsigned int i = 0; i < segs_.size(); ++i ) {
70  const SwcSegment& s = segs_[i];
71  if ( s.myIndex() != i + 1 )
72  badIndex++;
73  if ( s.parent() == ~0U ) {
74  numStart++;
75  } else {
76  if ( s.parent() > i ) {
77  numOrphans++;
78  }
79  }
80  if ( s.radius() < MinRadius ) {
81  badRadius++;
82  }
83  }
84  bool valid = ( numStart == 1 && numOrphans == 0 && badRadius == 0 );
85  if ( !valid ) {
86  cout << "ReadSwc::validate() failed: \nNumSegs = " <<
87  segs_.size() <<
88  ", numStart = " << numStart <<
89  ", orphans = " << numOrphans <<
90  ", badIndex = " << badIndex <<
91  ", badRadius = " << badRadius <<
92  ", numBranches = " << branches_.size() <<
93  endl;
94  }
95  return valid;
96 }
97 
99 {
100  for ( unsigned int i = 0; i < segs_.size(); ++i ) {
101  const SwcSegment& s = segs_[i];
102  assert ( s.parent() != s.myIndex() );
103  if ( s.parent() != ~0U ) {
104  segs_[s.parent() - 1].addChild( i + 1 );
105  }
106  }
107  for ( unsigned int i = 0; i < segs_.size(); ++i ) {
108  segs_[i].figureOutType();
109  }
110 }
111 
113 {
114  static double EPSILON = 1e-2; // Assume units in microns.
115  for ( unsigned int i = 1; i < segs_.size(); ++i ) {
116  SwcSegment& s = segs_[i];
117  SwcSegment& pa = segs_[ s.parent() - 1 ];
118  if ( s.distance( pa ) < EPSILON ) {
119  // Remove the zero length child from pa.kids_
120  vector< int > temp;
121  for ( unsigned int j = 0; j < pa.kids().size(); ++j ) {
122  if ( static_cast< unsigned int >( pa.kids()[j] ) != s.myIndex() )
123  temp.push_back( pa.kids()[j] );
124  }
125  // Go through all kids of s and reparent them.
126  for ( unsigned int j = 0; j < s.kids().size(); ++j ) {
127  SwcSegment& kid = segs_[ s.kids()[j] - 1 ];
128  kid.setParent( pa.myIndex() );
129  temp.push_back( kid.myIndex() );
130  }
131  pa.replaceKids( temp );
132  s.setBad();
133  cout << "ReadSwc:: Cleaned zero length " << s.myIndex() << endl;
134  }
135  }
136 }
137 
139  double& len, double& L, vector< int >& cable ) const
140 {
141  const SwcSegment* prev = &s;
142  cable.resize( 1, s.myIndex() ); // Always include the starting seg.
143  // Note that the cable is filled up with entries in reverse order.
144 
145  if ( s.parent() == ~0U ) {
146  len = s.radius();
147  L = sqrt( len );
148  return ;
149  }
150 
151  do {
152  // Beware the indexing!
153  const SwcSegment& pa = segs_[prev->parent() - 1];
154  len += pa.distance( *prev );
155  L += pa.L( );
156  cable.push_back( pa.myIndex() );
157  prev = &pa;
158  } while ( (prev->parent() != ~0U) && (prev->kids().size() == 1) );
159  cable.pop_back(); // Get rid of the last entry, it is on the parent.
160 }
161 
163 {
164  // Fill vector of all branches.
165  for ( unsigned int i = 0; i < segs_.size(); ++i ) {
166  const SwcSegment& s = segs_[i];
167  if ( s.OK() && s.kids().size() != 1 ) { // Either use a fork or an end.
168  vector< int > cable;
169  // int branchIndex = branches_.
170  // branches_.push_back( i + 1 );
171  double len = 0;
172  double L = 0;
173  traverseBranch( s, len, L, cable );
174  // branchGeomLength_.push_back( len );
175  // branchElectroLength_.push_back( L );
176  SwcBranch br( branches_.size(), s, len, L, cable );
177  branches_.push_back( br );
178  }
179  }
180  // Assign the parent of each branch. This is known because the
181  // parent of the first segment in the branch is the last segment
182  // in the parent branch. I construct a reverse lookup table to find
183  // the branch # from its last segment number.
184  vector< int > reverseSeg ( segs_.size() + 1, 0 );
185  for ( unsigned int i = 0; i < branches_.size(); ++i )
186  reverseSeg[ branches_[i].segs_.back() ] = i;
187  for ( unsigned int i = 0; i < branches_.size(); ++i ) {
188  int parentSeg = segs_[ branches_[i].segs_[0] - 1 ].parent();
189  assert( parentSeg != 0 ); // Note that segment indices start from 1
190  branches_[i].setParent( reverseSeg[ parentSeg ] );
191  }
192 }
193 
195 {
196  vector< int > diag( 14 );
197  for ( unsigned int i = 0; i < segs_.size(); ++i ) {
198  const SwcSegment& s = segs_[i];
199  if ( s.type() < 14 )
200  diag[s.type()]++;
201  }
202  for ( int i = 0; i < 14; ++i )
203  cout << "ReadSwc::diagnostics: " << SwcSegment::typeName[i] << " : " << diag[i] << endl;
204 
205  /*
206  for ( unsigned int i = 0; i < branches_.size(); ++i )
207  branches_[i].printDiagnostics();
208  */
209 }
210 
211 static Id makeCompt( Id parent,
212  const SwcSegment& seg, const SwcSegment& pa,
213  double RM, double RA, double CM,
214  unsigned int i, unsigned int j )
215 {
216  Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );
217  double len = seg.radius() * 2.0;
218  string name = "soma";
219  Id compt;
220  double x0, y0, z0;
221  if ( seg.parent() != ~0U ) {
222  len = seg.distance( pa );
223  stringstream ss;
224  ss << SwcSegment::typeName[ seg.type() ] << "_" << i << "_" << j;
225  name = ss.str();
226  x0 = pa.vec().a0();
227  y0 = pa.vec().a1();
228  z0 = pa.vec().a2();
229  } else {
230  x0 = seg.vec().a0() - len;
231  y0 = seg.vec().a1();
232  z0 = seg.vec().a2();
233  }
234  assert( len > 0.0 );
235  compt = shell->doCreate( "Compartment", parent, name, 1 );
236  Eref er = compt.eref();
237  moose::CompartmentBase *cptr = reinterpret_cast< moose::CompartmentBase* >(
238  compt.eref().data() );
239  double xa = seg.radius() * seg.radius() * PI * 1e-12;
240  len *= 1e-6;
241  double dia = seg.radius() * 2.0e-6;
242  cptr->setRm( er, RM / ( len * dia * PI ) );
243  cptr->setRa( er, RA * len / xa );
244  cptr->setCm( er, CM * ( len * dia * PI ) );
245  cptr->setDiameter( dia );
246  cptr->setLength( len );
247  cptr->setX0( x0 * 1e-6 );
248  cptr->setY0( y0 * 1e-6 );
249  cptr->setZ0( z0 * 1e-6 );
250  cptr->setX( seg.vec().a0() * 1e-6 );
251  cptr->setY( seg.vec().a1() * 1e-6 );
252  cptr->setZ( seg.vec().a2() * 1e-6 );
253  return compt;
254 }
255 
256 bool ReadSwc::build( Id parent,
257  double lambda, double RM, double RA, double CM )
258 {
259  Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );
260  vector< Id > compts( segs_.size() );
261  for ( unsigned int i = 0; i < branches_.size(); ++i ) {
262  SwcBranch& br = branches_[i];
263  for ( unsigned int j = 0; j < br.segs_.size(); ++j ) {
264  Id compt;
265  SwcSegment& seg = segs_[ br.segs_[j] -1 ];
266  unsigned int paIndex = seg.parent();
267  if ( paIndex == ~0U ) { // soma
268  compt = makeCompt( parent, seg, seg, RM, RA, CM, i, j );
269  } else {
270  SwcSegment& pa = segs_[ paIndex - 1 ];
271  compt = makeCompt( parent, seg, pa, RM, RA, CM, i, j );
272  assert( compt != Id() );
273  assert( compts[ paIndex -1 ] != Id() );
274  shell->doAddMsg( "Single",
275  compts[paIndex-1], "axial", compt, "raxial" );
276  }
277  assert( compt != Id() );
278  compts[ seg.myIndex() -1 ] = compt;
279  }
280  }
281  return true;
282 }
void traverseBranch(const SwcSegment &s, double &len, double &L, vector< int > &cable) const
Definition: ReadSwc.cpp:138
vector< int > segs_
Definition: SwcSegment.h:202
void setX(double value)
bool validate() const
Definition: ReadSwc.cpp:63
char * data() const
Definition: Eref.cpp:41
void setBad()
Definition: SwcSegment.h:39
void replaceKids(const vector< int > &kids)
Definition: SwcSegment.h:67
double a0() const
Definition: Vec.h:34
double L() const
Definition: SwcSegment.h:83
void cleanZeroLength()
Definition: ReadSwc.cpp:112
unsigned short type() const
Definition: SwcSegment.h:72
void setZ(double value)
void parseBranches()
Definition: ReadSwc.cpp:162
void setLength(double length)
unsigned int parent() const
Definition: SwcSegment.h:44
static const double MinRadius
Definition: ReadSwc.cpp:22
double a2() const
Definition: Vec.h:40
const vector< int > & kids() const
Definition: SwcSegment.h:62
Eref eref() const
Definition: Id.cpp:125
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
unsigned int myIndex() const
Definition: SwcSegment.h:52
bool OK() const
Definition: SwcSegment.h:34
void setCm(const Eref &e, double Cm)
void assignKids()
Definition: ReadSwc.cpp:98
void diagnostics() const
Definition: ReadSwc.cpp:194
Definition: Eref.h:26
double distance(const SwcSegment &other) const
Definition: SwcSegment.h:87
double radius() const
Definition: SwcSegment.h:76
void setZ0(double value)
static char name[]
Definition: mfield.cpp:401
vector< SwcSegment > segs_
Definition: ReadSwc.h:37
vector< SwcBranch > branches_
Definition: ReadSwc.h:45
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
const double PI
Definition: consts.cpp:12
void setDiameter(double diameter)
const Vec & vec() const
Definition: SwcSegment.h:91
Definition: Id.h:17
double a1() const
Definition: Vec.h:37
void setRa(const Eref &e, double Ra)
void setParent(unsigned int pa)
Definition: SwcSegment.h:48
#define EPSILON
Definition: MatrixOps.h:28
ReadSwc(const string &fname)
Definition: ReadSwc.cpp:24
static const string typeName[]
Definition: SwcSegment.h:137
void setX0(double value)
static Id makeCompt(Id parent, const SwcSegment &seg, const SwcSegment &pa, double RM, double RA, double CM, unsigned int i, unsigned int j)
Definition: ReadSwc.cpp:211
void setRm(const Eref &e, double Rm)
Definition: Shell.h:43
bool build(Id parent, double lambda, double RM, double RA, double CM)
Definition: ReadSwc.cpp:256
void setY0(double value)
void setY(double value)