MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ReadCell.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-2007 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 "ReadCell.h"
13 #include "../utility/utility.h"
14 #include "../utility/numutil.h"
15 #include "CompartmentBase.h"
16 #include "Compartment.h"
17 #include "SymCompartment.h"
18 #include <fstream>
19 
20 double calcSurf( double, double );
21 
22 // ReadCell::ReadCell( const vector< double >& globalParms )
24  :
25  RM_( 10.0 ),
26  CM_( 0.01 ),
27  RA_( 1.0 ),
28  EREST_ACT_( -0.065 ),
29  ELEAK_( -0.065 ),
30 
31 #if 0
32  // Unused privates. Causes error when -Werror is enabled. Uncomment them
33  // appropriately when needed.
34  dendrDiam( 0.0 ),
35  aveLength( 0.0 ),
36  spineSurf( 0.0 ),
37  spineDens( 0.0 ),
38  spineFreq( 0.0 ),
39  membFactor( 0.0 ),
40 #endif
41 
42  erestFlag_( 0 ),
43  eleakFlag_( 0 ),
44 
45  cell_( Id() ),
46  currCell_( Id() ),
47 
48  lastCompt_( Id() ),
49  protoCompt_( Id() ),
50 
51  numCompartments_( 0 ),
52  numChannels_( 0 ),
53  numOthers_( 0 ),
54 
55  numProtoCompts_( 0 ),
56  numProtoChans_( 0 ),
57  numProtoOthers_( 0 ),
58 
59  graftFlag_( 0 ),
60  polarFlag_( 0 ),
61  relativeCoordsFlag_( 0 ),
62  doubleEndpointFlag_( 0 ),
63  symmetricFlag_( 0 ),
64 
65  shell_( reinterpret_cast< Shell* >( Id().eref().data() ) )
66 {
67  /*
68  assert( globalParms.size() == 5 );
69  if ( !isEqual( globalParms[0], 0.0 ) )
70  CM_ = globalParms[0];
71  if ( !isEqual( globalParms[1], 0.0 ) )
72  RM_ = globalParms[1];
73  if ( !isEqual( globalParms[2], 0.0 ) )
74  RA_ = globalParms[2];
75  if ( !isEqual( globalParms[3], 0.0 ) )
76  EREST_ACT_ = globalParms[3];
77  if ( !isEqual( globalParms[4], 0.0 ) )
78  ELEAK_ = globalParms[4];
79  else
80  ELEAK_ = EREST_ACT_;
81  */
82 
83  string libPath = "/library";
84  Id libId( libPath );
85 
86  if ( libId.path() != libPath ) {
87  cerr << "Warning: ReadCell: No library for channels.\n";
88  return;
89  }
90 
91  vector< Id > chanList =
92  Field< vector< Id > >::get(
93  ObjId( libId ), "children" );
94 
95  vector< Id >::iterator i;
96  for ( i = chanList.begin(); i != chanList.end(); ++i ) {
97  Id id = (*i);
98  string name = id.element()->getName();
99 
100  chanProtos_[ name ] = id;
101  }
102 }
103 
109  const string& fileName,
110  const string& cellName,
111  Id parent )
112 {
113  fileName_ = fileName;
114 
115  ifstream fin( fileName.c_str() );
116  if ( !fin ) {
117  cerr << "ReadCell::read -- could not open file " << fileName << ".\n";
118  return Id();
119  }
120 
121  /*
122  // Search for file in list of paths.
123  PathUtility pathUtil( Property::getProperty( Property::SIMPATH ) );
124  ifstream fin( filename.c_str() );
125  for (unsigned int i = 0; i < pathUtil.size() && !fin; ++i )
126  {
127  string path = pathUtil.makeFilePath(filename, i);
128  fin.clear( );
129  fin.open( path.c_str() );
130  }
131  if ( !fin ) {
132  cerr << "ReadCell::read -- could not open file " << filename << endl;
133  return Id();
134  }
135  */
136 
137  unsigned int size = 1;
138  if ( parent.element()->cinfo()->isA( "Neuron" ) ) {
139  cell_ = parent;
140  currCell_ = cell_;
141  } else {
142  cell_ = shell_->doCreate( "Neuron", parent,
143  cellName, size, MooseGlobal );
144  currCell_ = cell_;
145  }
146 
147  if ( innerRead( fin ) ) {
148  return cell_;
149  } else {
150  cerr << "Readcell failed.\n";
151  return Id();
152  }
153 }
154 
155 bool ReadCell::innerRead( ifstream& fin )
156 {
157  string line;
158  lineNum_ = 0;
159 
160  ParseStage parseMode = DATA;
161  string::size_type pos;
162 
163  while ( getline( fin, line ) ) {
164  line = moose::trim( line );
165  lineNum_++;
166 
167  if ( line.length() == 0 )
168  continue;
169 
170  pos = line.find_first_not_of( "\t " );
171  if ( pos == string::npos )
172  continue;
173  else
174  line = line.substr( pos );
175 
176  if ( line.substr( 0, 2 ) == "//" )
177  continue;
178 
179  if ( ( pos = line.find( "//" ) ) != string::npos )
180  line = line.substr( 0, pos );
181 
182  if ( line.substr( 0, 2 ) == "/*" ) {
183  parseMode = COMMENT;
184  } else if ( line.find( "*/" ) != string::npos ) {
185  parseMode = DATA;
186  continue;
187  } else if ( line[ 0 ] == '*' ) {
188  parseMode = SCRIPT;
189  }
190 
191  if ( parseMode == COMMENT ) {
192  pos = line.find( "*/" );
193  if ( pos != string::npos ) {
194  parseMode = DATA;
195  if ( line.length() > pos + 2 )
196  line = line.substr( pos + 2 );
197  }
198  }
199 
200  if ( parseMode == DATA ) {
201  // For now not keeping it strict. Ignoring return status, and
202  // continuing even if there was error in processing this line.
203  readData( line );
204  } else if ( parseMode == SCRIPT ) {
205  // For now not keeping it strict. Ignoring return status, and
206  // continuing even if there was error in processing this line.
207  readScript( line );
208  parseMode = DATA;
209  }
210  }
211 
212  cout <<
213  "ReadCell: " <<
214  numCompartments_ << " compartments, " <<
215  numChannels_ << " channels, " <<
216  numOthers_ << " others\n";
217 
218  return 1;
219 }
220 
221 bool ReadCell::readScript( const string& line )
222 {
223  vector< string > argv;
224  string delimiters( "\t " );
225  moose::tokenize( line, delimiters, argv );
226 
227  if ( argv[ 0 ] == "*cartesian" ) {
228  polarFlag_ = 0;
229  } else if ( argv[ 0 ] == "*polar" ) {
230  polarFlag_ = 1;
231  } else if ( argv[ 0 ] == "*relative" ) {
233  } else if ( argv[ 0 ] == "*absolute" ) {
235  } else if ( argv[ 0 ] == "*symmetric" ) {
236  symmetricFlag_ = 1;
237  } else if ( argv[ 0 ] == "*asymmetric" ) {
238  symmetricFlag_ = 0;
239  } else if ( argv[ 0 ] == "*set_global" || argv[ 0 ] == "*set_compt_param" ) {
240  if ( argv.size() != 3 ) {
241  cerr << "Error: ReadCell: Bad line: " <<
242  "File: " << fileName_ <<
243  "Line: " << lineNum_ << "\n";
244  return 0;
245  }
246 
247  if ( argv[ 1 ] == "RM" )
248  RM_ = atof( argv[ 2 ].c_str() );
249  if ( argv[ 1 ] == "RA" )
250  RA_ = atof( argv[ 2 ].c_str() );
251  if ( argv[ 1 ] == "CM" )
252  CM_ = atof( argv[ 2 ].c_str() );
253  if ( argv[ 1 ] == "EREST_ACT" ) {
254  EREST_ACT_ = atof( argv[ 2 ].c_str() );
255  erestFlag_ = 1;
256  } if (argv[ 1 ] == "ELEAK" ) {
257  ELEAK_ = atof( argv[ 2 ].c_str() );
258  eleakFlag_ = 1;
259  }
260  } else if ( argv[ 0 ] == "*start_cell" ) {
261  if ( argv.size() == 1 ) {
262  graftFlag_ = 0;
263  currCell_ = cell_;
264  } else if ( argv.size() == 2 ) {
265  graftFlag_ = 1;
266  currCell_ = startGraftCell( argv[ 1 ] );
267  if ( currCell_ == Id() )
268  return 0;
269  } else {
270  cerr << "Error: ReadCell: Bad line: " <<
271  "File: " << fileName_ <<
272  "Line: " << lineNum_ << "\n";
273  return 0;
274  }
275  } else if ( argv[ 0 ] == "*compt" ) {
276  if ( argv.size() != 2 ) {
277  cerr << "Error: ReadCell: Bad line: " <<
278  "File: " << fileName_ <<
279  "Line: " << lineNum_ << "\n";
280  return 0;
281  }
282 
283  Id protoId( argv[ 1 ] );
284  if ( protoId.path() != argv[ 1 ] ) {
285  cerr << "Error: ReadCell: Bad path: " << argv[ 1 ] << " " <<
286  "File: " << fileName_ <<
287  "Line: " << lineNum_ << "\n";
288  return 0;
289  }
290 
291  protoCompt_ = protoId;
292  countProtos();
293  } else if ( argv[ 0 ] == "*double_endpoint" ) {
295  } else if ( argv[ 0 ] == "*double_endpoint_off" ) {
297  } else if ( argv[ 0 ] == "*makeproto" ) {
298  ; // Nothing to be done.
299  } else {
300  cerr << "Warning: ReadCell: Command " <<
301  argv[ 0 ] << " not recognized. Ignoring. " <<
302  "File: " << fileName_ <<
303  "Line: " << lineNum_ << "\n";
304  }
305 
306  return 1;
307 }
308 
309 bool ReadCell::readData( const string& line )
310 {
311  vector< string > argv;
312  string delimiters( "\t " );
313  moose::tokenize( line, delimiters, argv );
314 
315  if ( argv.size() < 6 ) {
316  cerr << "Error: ReadCell: Too few arguments in line: " << argv.size() <<
317  ", should be > 6.\n";
318  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
319  return 0;
320  }
321 
322  double x0 = 0.0;
323  double y0 = 0.0;
324  double z0 = 0.0;
325  double x, y, z;
326  double d;
327  int argOffset = 0;
328 
329  string name = argv[ 0 ];
330  string parent = argv[ 1 ];
331 
332  if ( doubleEndpointFlag_ ) {
333  argOffset = 3;
334 
335  x0 = 1.0e-6 * atof( argv[ 2 ].c_str() );
336  y0 = atof( argv[ 3 ].c_str() );
337  z0 = atof( argv[ 4 ].c_str() );
338  if ( polarFlag_ ) {
339  double r = x0;
340  double theta = y0 * M_PI / 180.0;
341  double phi = z0 * M_PI / 180.0;
342  x0 = r * sin( phi ) * cos ( theta );
343  y0 = r * sin( phi ) * sin ( theta );
344  z0 = r * cos( phi );
345  } else {
346  y0 *= 1.0e-6;
347  z0 *= 1.0e-6;
348  }
349  }
350 
351  x = 1.0e-6 * atof( argv[ argOffset + 2 ].c_str() );
352  y = atof( argv[ argOffset + 3 ].c_str() );
353  z = atof( argv[ argOffset + 4 ].c_str() );
354  if ( polarFlag_ ) {
355  double r = x;
356  double theta = y * M_PI / 180.0;
357  double phi = z * M_PI / 180.0;
358  x = r * sin( phi ) * cos ( theta );
359  y = r * sin( phi ) * sin ( theta );
360  z = r * cos( phi );
361  } else {
362  y *= 1.0e-6;
363  z *= 1.0e-6;
364  }
365 
366  d = 1.0e-6 * atof( argv[ argOffset + 5 ].c_str() );
367 
368  double length;
369  Id compt =
370  buildCompartment( name, parent, x0, y0, z0, x, y, z, d, length, argv );
371 
372  if ( compt == Id() )
373  return 0;
374 
375  return buildChannels( compt, argv, d, length );
376 }
377 
379  const string& name,
380  const string& parent,
381  double x0, double y0, double z0,
382  double x, double y, double z,
383  double d,
384  double& length, // Length is sent back.
385  vector< string >& argv )
386 {
387  static const Finfo* raxial2OutFinfo =
388  SymCompartment::initCinfo()->findFinfo( "distalOut" );
389  /*
390  * This section determines the parent compartment, to connect up with axial
391  * messages. Here 'parent' refers to the biophysical relationship within
392  * the neuron's tree, and not to the path hierarchy in the MOOSE element
393  * tree.
394  *
395  * If the parent is specified as 'none', then the compartment is the root
396  * of the cell's tree, and will not be connected axially to any compartments
397  * except for its children, if any.
398  */
399  Id parentId;
400  if ( parent == "." ) { // Shorthand: use the previous compartment.
401  parentId = lastCompt_;
402  } else if ( parent == "none" || parent == "nil" ) {
403  parentId = Id();
404  } else {
405  string parentPath = currCell_.path() + "/" + parent;
406  ObjId parentObjId = ObjId( parentPath );
407  if ( parentObjId.bad() ) {
408  cerr << "Error: ReadCell: could not find parent compt '"
409  << parent
410  << "' for child '" << name << "'.\n";
411  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
412  return ObjId(0, BADINDEX);
413  }
414  parentId = parentObjId;
415  }
416 
417  //~ Id childId;
418  //~ bool ret = lookupGet< Id, string >(
419  //~ currCell_, "lookupChild", childId, name );
420  //~ assert( ret );
421  //~ if ( !childId.bad() ) {
422  //~ if ( name[ name.length() - 1 ] == ']' ) {
423  //~ string::size_type pos = name.rfind( '[' );
424  //~ if ( pos == string::npos ) {
425  //~ cerr << "Error: ReadCell: bad child name:" << name << endl;
426  //~ cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
427  //~ return 0;
428  //~ }
429  //~ unsigned int index =
430  //~ atoi( name.substr( pos + 1, name.length() - pos ).c_str() );
431  //~ if ( childId.index() == index ) {
432  //~ cerr << "Error: ReadCell: duplicate child on parent compt '" <<
433  //~ parent << "' for child '" << name << "'\n";
434  //~ cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
435  //~ return 0;
436  //~ }
437  //~ } else {
438  //~ cerr << "Error: ReadCell: duplicate child on parent compt '" <<
439  //~ parent << "' for child '" << name << "'\n";
440  //~ cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
441  //~ return 0;
442  //~ }
443  //~ }
444 
445  unsigned int size = 1;
446  Id compt;
447  if ( graftFlag_ && ( parent == "none" || parent == "nil" ) ) {
448  compt = currCell_;
449  } else {
450  if ( protoCompt_ != Id() ) {
451  compt = shell_->doCopy(
452  protoCompt_,
453  currCell_,
454  name,
455  1, // n: number of copies
456  false, // toGlobal
457  false // copyExtMsgs
458  );
462  } else {
463  string comptType = ( symmetricFlag_ ) ?
464  "SymCompartment" : "Compartment";
465  compt = shell_->doCreate(
466  comptType, currCell_, name, size, MooseGlobal );
467  if ( !graftFlag_ )
469  }
470  }
471  lastCompt_ = compt;
472 
473  if ( parentId != Id()){
474  double px, py, pz;
475  double dx, dy, dz;
476 
477  px = Field< double >::get( parentId, "x" );
478  py = Field< double >::get( parentId, "y" );
479  pz = Field< double >::get( parentId, "z" );
480 
481  if ( !doubleEndpointFlag_ ) {
482  x0 = px;
483  y0 = py;
484  z0 = pz;
485  }
486 
487  if ( relativeCoordsFlag_ == 1 ) {
488  x += px;
489  y += py;
490  z += pz;
491  if ( doubleEndpointFlag_ ) {
492  x0 += px;
493  y0 += py;
494  z0 += pz;
495  }
496  }
497  dx = x - x0;
498  dy = y - y0;
499  dz = z - z0;
500 
501  length = sqrt( dx * dx + dy * dy + dz * dz );
502  if ( symmetricFlag_ ) {
503  // Now find all sibling compartments on the same parent.
504  // They must be connected up using 'sibling'.
505  vector< Id > sibs;
506  parentId.element()->getNeighbors( sibs, raxial2OutFinfo );
507  // Later put in the soma as a sphere, with its special msgs.
508  shell_->doAddMsg( "Single",
509  parentId, "distal", compt, "proximal" );
510  for ( vector< Id >::iterator i = sibs.begin();
511  i != sibs.end(); ++i ) {
512  shell_->doAddMsg( "Single",
513  compt, "sibling", *i, "sibling" );
514  }
515 
516  } else {
517  shell_->doAddMsg( "Single",
518  parentId, "axial", compt, "raxial" );
519  }
520  } else {
521  length = sqrt( x * x + y * y + z * z );
522  // or it could be a sphere.
523  }
524 
525  double Cm, Rm, Ra;
526 
527  Cm = CM_ * calcSurf( length, d );
528  Rm = RM_ / calcSurf( length, d );
529 
530  if ( length > 0 ) {
531  Ra = RA_ * length * 4.0 / ( d * d * M_PI );
532  } else {
533  Ra = RA_ * 8.0 / ( d * M_PI );
534  }
535 
536  // Set each of these to the other only if the only one set was other
537  double eleak = ( erestFlag_ && !eleakFlag_ ) ? EREST_ACT_ : ELEAK_;
538  double erest = ( !erestFlag_ && eleakFlag_ ) ? ELEAK_ : EREST_ACT_;
539 
540  Field< double >::set( compt, "x0", x0 );
541  Field< double >::set( compt, "y0", y0 );
542  Field< double >::set( compt, "z0", z0 );
543  Field< double >::set( compt, "x", x );
544  Field< double >::set( compt, "y", y );
545  Field< double >::set( compt, "z", z );
546  Field< double >::set( compt, "diameter", d );
547  Field< double >::set( compt, "length", length );
548  Field< double >::set( compt, "Rm", Rm );
549  Field< double >::set( compt, "Ra", Ra );
550  Field< double >::set( compt, "Cm", Cm );
551  Field< double >::set( compt, "initVm", erest );
552  Field< double >::set( compt, "Em", eleak );
553  Field< double >::set( compt, "Vm", erest );
554 
555  return compt;
556 }
557 
558 Id ReadCell::startGraftCell( const string& cellPath )
559 {
560  /*
561  * If path exists, return with error. This will also catch the case where
562  * cellPath is "/", and we will not have to check for this separately
563  * later.
564  */
565  Id cellId( cellPath );
566  if ( cellId.path() == cellPath ) {
567  cerr << "Warning: ReadCell: cell '" << cellPath << "' already exists.\n";
568  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
569  return Id();
570  }
571 
572  ObjId parentObjId;
573  string cellName;
574  string::size_type pos_1 = cellPath.find_first_of( "/" );
575  string::size_type pos_2 = cellPath.find_last_of( "/" );
576 
577  if ( pos_1 != 0 ) {
578  cerr << "Error: ReadCell: *start_cell should be given absolute path.\n";
579  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
580  return Id();
581  }
582 
583  if ( pos_2 == 0 ) {
584  parentObjId = ObjId("/");
585  cellName = cellPath.substr( 1 );
586  } else {
587  string parentPath = cellPath.substr( 0, pos_2 );
588  parentObjId = ObjId( parentPath );
589  if ( parentObjId.bad() ) {
590  cerr << "Error: ReadCell: cell path '" << cellPath
591  << "' not found.\n";
592  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
593  return Id();
594  }
595 
596  cellName = cellPath.substr( pos_2 + 1 );
597  }
598 
599  unsigned int size = 1;
600  return shell_->doCreate( "Compartment", parentObjId, cellName, size, MooseGlobal );
601 }
602 
603 Id ReadCell::findChannel( const string& name )
604 {
605  //~ vector< Id >::iterator i;
606  //~ for ( i = chanProtos_.begin(); i != chanProtos_.end(); i++ )
607  //~ if ( i->name() == name )
608  //~ return *i;
609  //~ return Id();
610 
611  map< string, Id >::iterator pos = chanProtos_.find( name );
612  if ( pos != chanProtos_.end() )
613  return pos->second;
614  else
615  return Id();
616 }
617 
618 double calcSurf( double len, double dia )
619 {
620  double area = 0.0;
621  if ( len == 0.0 ) // Spherical. Safe to compare with 0.0.
622  area = dia * dia * M_PI;
623  else
624  area = len * dia * M_PI;
625 
626  return area;
627 }
628 
630  Id compt,
631  vector< string >& argv,
632  double diameter,
633  double length )
634 {
635  bool isArgOK;
636  int argStart;
637  vector< Id > goodChannels;
638 
639  if ( doubleEndpointFlag_ ) {
640  isArgOK = ( argv.size() % 2 ) == 1;
641  argStart = 9;
642  } else {
643  isArgOK = ( argv.size() % 2 ) == 0;
644  argStart = 6;
645  }
646 
647  if ( !isArgOK ) {
648  cerr << "Error: ReadCell: Bad number of arguments in channel list\n";
649  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
650  return 0;
651  }
652 
653  for ( unsigned int j = argStart; j < argv.size(); j++ ) {
654  // Here we explicitly set compt fields by scaling from the
655  // specific value applied here.
656  string chan = argv[ j ];
657 
658  double value = atof( argv[ ++j ].c_str() );
659  if ( chan == "RA" ) {
660  double temp;
661  if ( length == 0.0 ) // Spherical flag. Assume length = dia.
662  temp = 8.0 * value / ( diameter * M_PI );
663  else
664  temp = 4.0 * value * length / ( diameter * diameter * M_PI );
665  Field< double >::set( compt, "Ra", temp );
666  } else if ( chan == "RM" ) {
667  Field< double >::set( compt, "Rm", value * calcSurf( length, diameter ) );
668  } else if ( chan == "CM" ) {
669  Field< double >::set( compt, "Cm", value * calcSurf( length, diameter ) );
670  } else if ( chan == "Rm" ) {
671  Field< double >::set( compt, "Rm", value );
672  } else if ( chan == "Ra" ) {
673  Field< double >::set( compt, "Ra", value );
674  } else if ( chan == "Cm" ) {
675  Field< double >::set( compt, "Cm", value );
676  } else if ( chan == "kinModel" ) {
677  // Need 3 args here:
678  // lambda, name of proto, method
679  // We already have lambda from value. Note it is in microns
680  if ( j + 2 < argv.size() ) {
681  string protoName = argv[ ++j ];
682  string method = argv[ ++j ];
683  //~ addKinModel( compt, value * 1.0e-6, protoName, method );
684  } else {
685  cerr << "Error: ReadCell: kinModel needs 3 args\n";
686  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
687  break;
688  }
689  } else if ( chan == "m2c" ) {
690  // Need 5 args here:
691  // scale factor, mol, moloffset, chan, chanoffset
692  // We already have scale factor from value.
693  if ( j + 4 < argv.size() ) {
694  //~ addM2C( compt, value, argv.begin() + j + 1 );
695  j += 4;
696  } else {
697  cerr << "Error: ReadCell: m2c adaptor needs 5 args\n";
698  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
699  break;
700  }
701  } else if ( chan == "c2m" ) {
702  // Need another 5 args here:
703  // scale factor, chan, chanoffset, mol, moloffset
704  if ( j + 4 < argv.size() ) {
705  //~ addC2M( compt, value, argv.begin() + j + 1 );
706  j += 4;
707  } else {
708  cerr << "Error: ReadCell: c2m adaptor needs 5 args\n";
709  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
710  break;
711  }
712  } else {
713  Id chanId = findChannel( chan );
714  if ( chanId == Id() ) {
715  cerr << "Error: ReadCell: Channel '" << chan <<
716  "' not found\n";
717  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
718  continue;
719  }
720 
721  Id copy = addChannel( compt, chanId, value, diameter, length );
722  if ( copy != Id() ) {
723  goodChannels.push_back( copy );
724  } else {
725  cerr << "Error: ReadCell: Could not add " << chan
726  << " in " << compt.element()->getName() << ".";
727  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
728  }
729  }
730  }
731 
732  for ( unsigned int i = 0; i < goodChannels.size(); i++ )
733  addChannelMessage( goodChannels[ i ] );
734 
735  return 1;
736 }
737 
739  Id compt,
740  Id proto,
741  double value,
742  double dia,
743  double length )
744 {
745  Id copy = shell_->doCopy(
746  proto,
747  compt,
748  "", // newName: same as old name.
749  1, // n: number of copies
750  false, // toGlobal
751  false // copyExtMsgs
752  );
754  assert( copy.element()->getName() == proto.element()->getName() );
756  assert( copy != Id() );
757 
758  if ( addCanonicalChannel( compt, copy, value, dia, length ) ) return copy;
759  if ( addSpikeGen( compt, copy, value, dia, length ) ) return copy;
760  if ( addCaConc( compt, copy, value, dia, length ) ) return copy;
761  if ( addNernst( compt, copy, value ) ) return copy;
762 
763  return Id();
764 }
765 
775  Id compt,
776  Id chan,
777  double value,
778  double dia,
779  double length )
780 {
781  string className = chan.element()->cinfo()->name();
782  if (
783  className == "HHChannel" ||
784  className == "HHChannel2D" ||
785  className == "SynChan" ||
786  className == "NMDAChan"
787  ) {
788  ObjId mid = shell_->doAddMsg(
789  "Single",
790  compt,
791  "channel",
792  chan,
793  "channel"
794  );
795  if ( mid.bad() )
796  cout << "failed to connect message from compt " << compt <<
797  " to channel " << chan << endl;
798 
799  if ( value > 0 ) {
800  value *= calcSurf( length, dia );
801  } else {
802  value = -value;
803  }
804 
805  if ( !graftFlag_ )
806  ++numChannels_;
807 
808  return Field< double >::set( chan, "Gbar", value );
809  }
810 
811  return 0;
812 }
813 
815  Id compt,
816  Id chan,
817  double value,
818  double dia,
819  double length )
820 {
821  string className = chan.element()->cinfo()->name();
822  if ( className == "SpikeGen" ) {
823  shell_->doAddMsg(
824  "Single",
825  compt,
826  "VmOut",
827  chan,
828  "Vm"
829  );
830 
831  if ( !graftFlag_ )
832  ++numOthers_;
833 
834  return Field< double >::set( chan, "threshold", value );
835  }
836 
837  return 0;
838 }
839 
840 /*
841  * At present this does not set up any messaging. Traditionally (in GENESIS),
842  * information on how to set customized messaging is stored in extra 'addmsg'
843  * fields created on channels and other objects. Here the 'addChannelMessage()'
844  * function handles these 'addmsg' fields.
845  */
847  Id compt,
848  Id chan,
849  double value,
850  double dia,
851  double length )
852 {
853  double thickness = Field< double >::get( chan, "thick" );
854  if ( thickness > dia / 2.0 )
855  thickness = 0.0;
856 
857  string className = chan.element()->cinfo()->name();
858  if ( className == "CaConc" ) {
859  if ( value > 0.0 ) {
860  double vol;
861  if ( length > 0.0 ){
862  if ( thickness > 0.0 ) {
863  vol = M_PI * length * ( dia - thickness ) * thickness;
864  } else {
865  vol = dia * dia * M_PI * length / 4.0;
866  }
867  } else { // spherical
868  if ( thickness > 0.0 ) {
869  double inner_dia = dia - 2 * thickness;
870  vol = M_PI * (
871  dia * dia * dia -
872  inner_dia * inner_dia * inner_dia
873  ) / 6.0;
874  } else {
875  vol = M_PI * dia * dia * dia / 6.0;
876  }
877  }
878  if ( vol > 0.0 ) // Scale by volume.
879  value /= vol;
880  } else {
881  value = - value;
882  }
883 
884  if ( !graftFlag_ )
885  ++numOthers_;
886 
887  return Field< double >::set( chan, "B", value );
888  }
889 
890  return 0;
891 }
892 
894  Id compt,
895  Id chan,
896  double value )
897 {
898  if ( !graftFlag_ )
899  ++numOthers_;
900  return 0;
901 }
902 
903 /*
904 void ReadCell::addKinModel( Element* compt, double lambda,
905  string name, string method )
906 {
907  // cout << "addKinModel on " << compt->name() <<
908  // " name= " << name << ", lambda = " << lambda <<
909  // ", using " << method << endl;
910 
911  Element* kinElm = findChannel( name );
912  if ( kinElm == 0 ) {
913  cerr << "Error:ReadCell: KinProto '" << name << "' not found\n";
914  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
915  return;
916  }
917 
918  Element* kph = Neutral::create( "KinPlaceHolder", "kinModel",
919  compt->id(), Id::childId( compt->id() ) );
920  set< Id, double, string >( kph, "setup",
921  kinElm->id(), lambda, method );
922 }
923 
924 void ReadCell::addM2C( Element* compt, double scale,
925  vector< string >::iterator args )
926 {
927  // cout << "addM2C on " << compt->name() <<
928  // " scale= " << scale <<
929  // " mol= " << *args << ", moloff= " << *(args+1) <<
930  // " chan= " << *(args + 2) << ", chanoff= " << *(args+3) << endl;
931 
932  string molName = *args++;
933  double molOffset = atof( ( *args++ ).c_str() );
934  string chanName = *args++;
935  double chanOffset = atof( ( *args ).c_str() );
936  string adaptorName = molName + "_2_" + chanName;
937 
938  Element* chan = findChannel( chanName );
939  if ( chan == 0 ) {
940  cerr << "Error:ReadCell: addM2C ': channel" << chanName <<
941  "' not found\n";
942  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
943  return;
944  }
945 
946  Element* adaptor = Neutral::create( "Adaptor", adaptorName,
947  compt->id(), Id::childId( compt->id() ) );
948 
949  Eref( adaptor ).add( "outputSrc", Eref( chan ), "Gbar" );
950  set< string, double, double, double >( adaptor, "setup",
951  molName, scale, molOffset, chanOffset );
952 }
953 
954 void ReadCell::addC2M( Element* compt, double scale,
955  vector< string >::iterator args )
956 {
957  // cout << "addC2M on " << compt->name() <<
958  // " scale= " << scale <<
959  // " chan= " << *args << ", chanoff= " << *(args+1) <<
960  // " mol= " << *(args + 2) << ", moloff= " << *(args+3) << endl;
961 
962  string chanName = *args++;
963  double chanOffset = atof( ( *args++ ).c_str() );
964  string molName = *args++;
965  double molOffset = atof( ( *args++ ).c_str() );
966  string adaptorName = "Ca_2_" + molName;
967 
968  Element* chan = findChannel( chanName );
969  if ( chan == 0 ) {
970  cerr << "Error:ReadCell: addC2M ': channel" << chanName <<
971  "' not found\n";
972  cerr << "File: " << fileName_ << " Line: " << lineNum_ << endl;
973  return;
974  }
975 
976  Element* adaptor = Neutral::create( "Adaptor", adaptorName,
977  compt->id(), Id::childId( compt->id() ) );
978 
979  Eref( adaptor ).add( "inputRequest", Eref( chan ), "Ca" );
980  set< string, double, double, double >( adaptor, "setup",
981  molName, scale, chanOffset, molOffset );
982 }
983 */
984 
986 {
987  /*
988  * Get child objects of type Mstring, named addmsg1, 2, etc.
989  * These define extra messages to be assembled at setup.
990  * Similar to what was done with GENESIS.
991  */
992  vector< Id > kids;
993  Neutral::children( chan.eref(), kids );
994  Shell *shell = reinterpret_cast< Shell* >( Id().eref().data() );
995  Id cwe = shell->getCwe();
996  shell->setCwe( chan );
997  for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i )
998  {
999  // Ignore kid if its name does not begin with "addmsg"..
1000  const string& name = i->element()->getName();
1001  if ( name.find( "addmsg", 0 ) != 0 )
1002  continue;
1003 
1004  string s = Field< string >::get( *i, "value" );
1005  vector< string > token;
1006  moose::tokenize( s, " ", token );
1007  assert( token.size() == 4 );
1008  ObjId src = shell->doFind( token[0] );
1009  ObjId dest = shell->doFind( token[2] );
1010 
1011  // I would like to assert, or warn here, but there are legitimate
1012  // cases where not all possible messages are actually available
1013  // to set up. So I just bail.
1014  if ( src.bad() || dest.bad()) {
1015 #ifndef NDEBUG
1016  /*
1017  cout << "ReadCell::addChannelMessage( " << chan.path() <<
1018  "): " << name << " " << s <<
1019  ": Bad src " << src << " or dest " << dest << endl;
1020  */
1021 #endif
1022  continue;
1023  }
1024  ObjId mid =
1025  shell->doAddMsg( "single", src, token[1], dest, token[3] );
1026  assert( !mid.bad());
1027  }
1028  shell->setCwe( cwe );
1029 }
1030 
1035 {
1036  //~ if ( protoCompt_ == 0 )
1037  //~ return;
1038  //~
1039  //~ numProtoCompts_ = 1; // protoCompt_ itself
1040  //~ numProtoChans_ = 0;
1041  //~ numProtoOthers_ = 0;
1042 //~
1043  //~ vector< vector< Id > > cstack;
1044  //~ cstack.push_back( Neutral::getChildList( protoCompt_ ) );
1045  //~ while ( !cstack.empty() ) {
1046  //~ vector< Id >& child = cstack.back();
1047  //~
1048  //~ if ( child.empty() ) {
1049  //~ cstack.pop_back();
1050  //~ if ( !cstack.empty() )
1051  //~ cstack.back().pop_back();
1052  //~ } else {
1053  //~ const Id& curr = child.back();
1054  //~ const Cinfo* currCinfo = curr()->cinfo();
1055  //~
1056  //~ if ( currCinfo->isA( comptCinfo ) )
1057  //~ ++numProtoCompts_;
1058  //~ else if ( currCinfo->isA( chanCinfo ) ||
1059  //~ currCinfo->isA( synchanCinfo ) )
1060  //~ ++numProtoChans_;
1061  //~ else if ( currCinfo->isA( spikegenCinfo ) ||
1062  //~ currCinfo->isA( caconcCinfo ) ||
1063  //~ currCinfo->isA( nernstCinfo ) )
1064  //~ ++numProtoOthers_;
1065  //~
1066  //~ cstack.push_back( Neutral::getChildList( curr() ) );
1067  //~ }
1068  //~ }
1069 }
char * data() const
Definition: Eref.cpp:41
uint32_t value
Definition: moosemodule.h:42
bool addCanonicalChannel(Id compt, Id chan, double value, double dia, double length)
Definition: ReadCell.cpp:774
double EREST_ACT_
Definition: ReadCell.h:108
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
ParseStage
Definition: ReadCell.h:11
bool bad() const
Definition: ObjId.cpp:18
std::string path(const std::string &separator="/") const
Definition: Id.cpp:76
Definition: SetGet.h:236
unsigned int numOthers_
Definition: ReadCell.h:129
ReadCell()
Definition: ReadCell.cpp:23
bool buildChannels(Id compt, vector< string > &argv, double diameter, double length)
Definition: ReadCell.cpp:629
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.
Definition: ShellCopy.cpp:16
Id cell_
Definition: ReadCell.h:122
Definition: ObjId.h:20
double calcSurf(double, double)
Definition: ReadCell.cpp:618
Id buildCompartment(const string &name, const string &parent, double x0, double y0, double z0, double x, double y, double z, double d, double &length, vector< string > &argv)
Definition: ReadCell.cpp:378
Eref eref() const
Definition: Id.cpp:125
static void children(const Eref &e, vector< Id > &ret)
Definition: Neutral.cpp:342
Id addChannel(Id compt, Id chan, double value, double dia, double length)
Definition: ReadCell.cpp:738
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
unsigned int numChannels_
Definition: ReadCell.h:128
#define M_PI
Definition: numutil.h:34
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
Id lastCompt_
Definition: ReadCell.h:124
bool doubleEndpointFlag_
Definition: ReadCell.h:142
double ELEAK_
Definition: ReadCell.h:109
const std::string & name() const
Definition: Cinfo.cpp:260
map< string, Id > chanProtos_
Definition: ReadCell.h:145
Id read(const string &filename, const string &cellname, Id parent)
Definition: ReadCell.cpp:108
bool polarFlag_
Definition: ReadCell.h:140
unsigned int numCompartments_
Definition: ReadCell.h:127
bool innerRead(ifstream &fin)
Definition: ReadCell.cpp:155
bool addNernst(Id compt, Id chan, double value)
Definition: ReadCell.cpp:893
Id currCell_
Definition: ReadCell.h:123
unsigned int numProtoCompts_
Definition: ReadCell.h:131
static const Cinfo * initCinfo()
bool symmetricFlag_
Definition: ReadCell.h:143
bool isA(const string &ancestor) const
Definition: Cinfo.cpp:280
bool readData(const string &line)
Definition: ReadCell.cpp:309
bool readScript(const string &line)
Definition: ReadCell.cpp:221
const Cinfo * cinfo() const
Definition: Element.cpp:66
static void addChannelMessage(Id chan)
Definition: ReadCell.cpp:985
double CM_
Definition: ReadCell.h:106
Id findChannel(const string &name)
Definition: ReadCell.cpp:603
double RM_
Definition: ReadCell.h:105
bool graftFlag_
Definition: ReadCell.h:139
Id protoCompt_
Definition: ReadCell.h:125
static char name[]
Definition: mfield.cpp:401
Id startGraftCell(const string &cellPath)
Definition: ReadCell.cpp:558
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
unsigned int lineNum_
Definition: ReadCell.h:103
void tokenize(const string &str, const string &delimiters, vector< string > &tokens)
Definition: strutil.cpp:19
Shell * shell_
Definition: ReadCell.h:147
Definition: ReadCell.h:11
Definition: Id.h:17
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
Definition: Element.cpp:949
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
bool relativeCoordsFlag_
Definition: ReadCell.h:141
std::string trim(const std::string myString, const string &delimiters)
Definition: strutil.cpp:53
bool erestFlag_
Definition: ReadCell.h:119
bool eleakFlag_
Definition: ReadCell.h:120
static char id[]
Definition: mfield.cpp:404
void countProtos()
Definition: ReadCell.cpp:1034
const string & getName() const
Definition: Element.cpp:56
const unsigned int BADINDEX
Used by ObjId and Eref.
Definition: consts.cpp:25
unsigned int numProtoChans_
Definition: ReadCell.h:132
string fileName_
Definition: ReadCell.h:102
double RA_
Definition: ReadCell.h:107
Definition: Shell.h:43
bool addCaConc(Id compt, Id chan, double value, double dia, double length)
Definition: ReadCell.cpp:846
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
bool addSpikeGen(Id compt, Id chan, double value, double dia, double length)
Definition: ReadCell.cpp:814
Definition: Finfo.h:12
unsigned int numProtoOthers_
Definition: ReadCell.h:133