MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ReadKkit.cpp
Go to the documentation of this file.
1 
2 /**********************************************************************
3 ** This program is part of 'MOOSE', the
4 ** Messaging Object Oriented Simulation Environment.
5 ** Copyright (C) 2003-2010 Upinder S. Bhalla. and NCBS
6 ** It is made available under the terms of the
7 ** GNU Lesser General Public License version 2.1
8 ** See the file COPYING.LIB for the full notice.
9 **********************************************************************/
10 
11 
12 #include <iomanip>
13 #include <fstream>
14 #include "header.h"
15 #include "../utility/utility.h"
16 #include "PoolBase.h"
17 #include "Pool.h"
18 #include "BufPool.h"
19 #include "ReacBase.h"
20 #include "EnzBase.h"
21 #include "lookupVolumeFromMesh.h"
22 
23 #include "../shell/Shell.h"
24 #include "../shell/Wildcard.h"
25 
26 #include "ReadKkit.h"
27 
28 const double ReadKkit::EPSILON = 1.0e-15;
29 static const double KKIT_NA = 6.0e23; // Causes all sorts of conversion fun
30 
31 unsigned int chopLine( const string& line, vector< string >& ret )
32 {
33  ret.resize( 0 );
34  stringstream ss( line );
35  string arg;
36  while ( ss >> arg ) {
37  ret.push_back( moose::trim(arg, "\"") );
38  }
39  return ret.size();
40 }
41 
42 string lower( const string& input )
43 {
44  string ret = input;
45  for ( unsigned int i = 0; i < input.length(); ++i )
46  ret[i] = tolower( ret[i] );
47  return ret;
48 }
49 
51 
53  :
54  basePath_( "" ),
55  baseId_(),
56  fastdt_( 0.001 ),
57  simdt_( 0.01 ),
58  controldt_( 0.1 ),
59  plotdt_( 1 ),
60  maxtime_( 1.0 ),
61  transientTime_( 1.0 ),
62  useVariableDt_( 0 ),
63  defaultVol_( 1 ),
64  version_( 11 ),
65  initdumpVersion_( 3 ),
66  moveOntoCompartment_( true ),
67  numCompartments_( 0 ),
68  numPools_( 0 ),
69  numReacs_( 0 ),
70  numEnz_( 0 ),
71  numMMenz_( 0 ),
72  numPlot_( 0 ),
73  numStim_( 0 ),
74  numOthers_( 0 ),
75  lineNum_( 0 ),
76  shell_( reinterpret_cast< Shell* >( Id().eref().data() ) )
77 {
78  ;
79 }
80 
82 // Fields for readKkit
84 
85 double ReadKkit::getMaxTime() const
86 {
87  return maxtime_;
88 }
89 
90 double ReadKkit::getPlotDt() const
91 {
92  return plotdt_;
93 }
94 
96 {
97  return defaultVol_;
98 }
99 
100 string ReadKkit::getBasePath() const
101 {
102  return basePath_;
103 }
104 
105 unsigned int ReadKkit::getVersion() const
106 {
107  return version_;
108 }
109 
111 {
112  return moveOntoCompartment_;
113 }
114 
116 {
118 }
119 
121 // The read functions.
123 Id makeStandardElements( Id pa, const string& modelname )
124 {
125  Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() );
126  string modelPath = pa.path() + "/" + modelname;
127  if ( pa == Id() )
128  modelPath = "/" + modelname;
129  Id mgr( modelPath );
130  if ( mgr == Id() )
131  mgr = shell->doCreate( "Neutral", pa, modelname, 1, MooseGlobal );
132  Id kinetics( modelPath + "/kinetics" );
133  if ( kinetics == Id() ) {
134  kinetics =
135  shell->doCreate( "CubeMesh", mgr, "kinetics", 1, MooseGlobal );
136  SetGet2< double, unsigned int >::set( kinetics, "buildDefaultMesh", 1e-15, 1 );
137  }
138  assert( kinetics != Id() );
139 
140  Id graphs = shell->doCreate( "Neutral", mgr, "graphs", 1, MooseGlobal);
141  assert( graphs != Id() );
142  Id moregraphs = shell->doCreate( "Neutral", mgr, "moregraphs", 1, MooseGlobal );
143 
144  Id geometry = shell->doCreate( "Neutral", mgr, "geometry", 1, MooseGlobal );
145  assert( geometry != Id() );
146 
147  Id groups =
148  shell->doCreate( "Neutral", mgr, "groups", 1, MooseGlobal );
149  assert( groups != Id() );
150  return mgr;
151 }
152 
153 static void positionCompt( ObjId compt, double side, bool shiftUp )
154 {
155  double y0 = Field< double >::get( compt, "y0" );
156  double y1 = Field< double >::get( compt, "y1" );
157  if ( shiftUp ) {
158  Field< double >::set( compt, "y0", y0 + side );
159  Field< double >::set( compt, "y1", y1 + side );
160  } else {
161  Field< double >::set( compt, "y0", y0 - y1 );
162  Field< double >::set( compt, "y1", 0 );
163  }
164 }
165 
166 void makeSolverOnCompt( Shell* s,const vector< ObjId >& compts,
167  bool isGsolve )
168 {
169 
170  if ( compts.size() > 3 ) {
171  cout << "Warning: ReadKkit::makeSolverOnCompt: Cannot handle " <<
172  compts.size() << " chemical compartments\n";
173  return;
174  }
175  vector< Id > stoichVec;
176  /*
177  if ( compts.size() == 2 ) {
178  double side = Field< double >::get( compts[1], "dy" );
179  positionCompt( compts[0], side, true );
180  }
181  if ( compts.size() == 3 ) {
182  double side = Field< double >::get( compts[1], "dy" );
183  positionCompt( compts[0], side, true );
184  positionCompt( compts[2], side, false );
185  }
186  */
187  /*
188  for ( vector< ObjId >::const_iterator
189  i = compts.begin(); i != compts.end(); ++i ) {
190  string simpath = i->path() + "/##";
191  Id ksolve;
192  if ( isGsolve )
193  ksolve = s->doCreate( "Gsolve", *i, "gsolve", 1 );
194  else
195  ksolve = s->doCreate( "Ksolve", *i, "ksolve", 1 );
196  dsolve = s->doCreate("Dsolve,")
197  Id stoich = s->doCreate( "Stoich", *i, "stoich", 1 );
198  stoichVec.push_back( stoich );
199  Field< Id >::set( stoich, "compartment", *i );
200  Field< Id >::set( stoich, "ksolve", ksolve );
201  Field< string >::set( stoich, "path", simpath );
202  }
203  */
204  /* Not needed now that we use xfer pools to cross compartments.
205  if ( stoichVec.size() == 2 ) {
206  SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] );
207  }
208  if ( stoichVec.size() == 3 ) {
209  SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] );
210  SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[2] );
211  }
212  for ( vector< Id >::iterator
213  i = stoichVec.begin(); i != stoichVec.end(); ++i ) {
214  SetGet0::set( *i, "filterXreacs" );
215  }
216  */
217 }
218 
219 void setMethod( Shell* s, Id mgr, double simdt, double plotdt,
220  const string& method )
221 {
222  vector< ObjId > ret;
223  simpleWildcardFind( mgr.path() + "/#[ISA=ChemCompt]", ret );
224  assert( ret.size() > 0 );
225 
226  Id compt( mgr.path() + "/kinetics" );
227  assert( compt != Id() );
228  string simpath2 = mgr.path() + "/##[ISA=StimulusTable]," +
229  mgr.path() + "/##[ISA=PulseGen]";
230  string m = lower( method );
231  /*
232  if ( m == "ksolve" || m =="gsl" || m == "gssa" || m == "gsolve" ||
233  m == "gillespie" || m == "stochastic" )
234  {
235  cout << " Warning: Default solver set is Exponential Euler. To set \'gsl\' or \'gssa\' solver use function mooseaddChemSolver(modelpath,\'solverType\')"<<"\n";
236  }
237 
238 
239  if ( m == "rk4" ) {
240  cout << "Warning, not yet implemented. Using rk5 instead\n";
241  m = "rk5";
242  }
243  if ( m == "ksolve" || m == "gsl" ||
244  m == "rk5" || m == "rkf" || m == "rk" ) {
245  makeSolverOnCompt( s, mgr, ret, false );
246  } else if ( m == "gssa" || m == "gsolve" ||
247  m == "gillespie" || m == "stochastic" ) {
248  makeSolverOnCompt( s, mgr,ret, true );
249  } else if ( m == "ee" || m == "neutral" ) {
250  // s->doUseClock( simpath, "process", 4 );
251  // s->doSetClock( 4, simdt );
252  } else {
253  cout << "ReadKkit::setMethod: option " << method <<
254  " not known, using Exponential Euler (ee)\n";
255  // s->doUseClock( simpath, "process", 4 );
256  // s->doSetClock( 4, simdt );
257  }
258  */
259  s->doUseClock( simpath2, "proc", 11 );
260  s->doSetClock( 10, simdt );
261  s->doSetClock( 11, simdt );
262  s->doSetClock( 12, simdt );
263  s->doSetClock( 13, simdt );
264  s->doSetClock( 14, simdt );
265  s->doSetClock( 15, plotdt ); // Gsolve and Ksolve
266  s->doSetClock( 16, plotdt ); // Gsolve and Ksolve
267  s->doSetClock( 17, plotdt ); // Stats objects
268  s->doSetClock( 18, plotdt ); // Table2 objects.
269 }
277  const string& filename,
278  const string& modelname,
279  Id pa, const string& methodArg )
280 {
281  string method = methodArg;
282  ifstream fin( filename.c_str() );
283  if (!fin){
284  cerr << "ReadKkit::read: could not open file " << filename << endl;
285  return Id();
286  }
287 
288  if ( method.substr(0, 4) == "old_" ) {
289  moveOntoCompartment_ = false;
290  method = method.substr( 4 );
291  }
292 
293  Shell* s = reinterpret_cast< Shell* >( ObjId().data() );
294  Id mgr = makeStandardElements( pa, modelname );
295  assert( mgr != Id() );
296  baseId_ = mgr;
297  basePath_ = mgr.path();
298  enzCplxMols_.resize( 0 );
299 
300  innerRead( fin );
305 
307 
308  setMethod( s, mgr, simdt_, plotdt_, method );
309 
310  //Harsha: Storing solver and runtime at model level rather than model level
311  Id kinetics( basePath_+"/kinetics");
312  assert(kinetics != Id());
313  Id cInfo = s->doCreate( "Annotator", basePath_, "info", 1 );
314  assert( cInfo != Id() );
315  Field< string > ::set(cInfo, "solver", "ee");
316  Field< double > ::set(cInfo, "runtime", maxtime_);
317  s->doReinit();
318  return mgr;
319 }
320 
322 {
323  shell_->doSetClock( 11, simdt_ );
324  shell_->doSetClock( 12, simdt_ );
325  shell_->doSetClock( 13, simdt_ );
326  shell_->doSetClock( 14, simdt_ );
327  shell_->doSetClock( 16, plotdt_ );
328  shell_->doSetClock( 17, plotdt_ );
329  shell_->doSetClock( 18, plotdt_ );
330  shell_->doReinit();
331  if ( useVariableDt_ ) {
332  shell_->doSetClock( 11, fastdt_ );
333  shell_->doSetClock( 12, fastdt_ );
334  shell_->doSetClock( 13, fastdt_ );
335  shell_->doSetClock( 14, fastdt_ );
337  shell_->doSetClock( 11, simdt_ );
338  shell_->doSetClock( 12, simdt_ );
339  shell_->doSetClock( 13, simdt_ );
340  shell_->doSetClock( 14, simdt_ );
342  } else {
343  shell_->doStart( maxtime_ );
344  }
345 }
346 
347 void ReadKkit::dumpPlots( const string& filename )
348 {
349  // ofstream fout ( filename.c_str() );
350  vector< ObjId > plots;
351  string plotpath = basePath_ + "/graphs/##[TYPE=Table2]," +
352  basePath_ + "/moregraphs/##[TYPE=Table2]";
353  wildcardFind( plotpath, plots );
354  for ( vector< ObjId >::iterator
355  i = plots.begin(); i != plots.end(); ++i )
356  SetGet2< string, string >::set( *i, "xplot",
357  filename, i->element()->getName() );
358 }
359 
360 void ReadKkit::innerRead( ifstream& fin )
361 {
362  string line;
363  string temp;
364  lineNum_ = 0;
365  string::size_type pos;
366  bool clearLine = 1;
367  ParseMode parseMode = INIT;
368 
369  while ( getline( fin, temp ) ) {
370  lineNum_++;
371  if ( clearLine )
372  line = "";
373  temp = moose::trim(temp);
374  if ( temp.length() == 0 )
375  continue;
376  pos = temp.find_last_not_of( "\t " );
377  if ( pos == string::npos ) {
378  // Nothing new in line, go with what was left earlier,
379  // and clear out line for the next cycle.
380  temp = "";
381  clearLine = 1;
382  } else {
383  if ( temp[pos] == '\\' ) {
384  temp[pos] = ' ';
385  line.append( temp );
386  clearLine = 0;
387  continue;
388  } else {
389  line.append( temp );
390  clearLine = 1;
391  }
392  }
393 
394  pos = line.find_first_not_of( "\t " );
395  if ( pos == string::npos )
396  continue;
397  else
398  line = line.substr( pos );
399  if ( line.substr( 0, 2 ) == "//" )
400  continue;
401  if ( (pos = line.find("//")) != string::npos )
402  line = line.substr( 0, pos );
403  if ( line.substr( 0, 2 ) == "/*" ) {
404  parseMode = COMMENT;
405  line = line.substr( 2 );
406  }
407 
408  if ( parseMode == COMMENT ) {
409  pos = line.find( "*/" );
410  if ( pos != string::npos ) {
411  parseMode = DATA;
412  if ( line.length() > pos + 2 )
413  line = line.substr( pos + 2 );
414  }
415  }
416 
417  if ( parseMode == DATA )
418  readData( line );
419  else if ( parseMode == INIT ) {
420  parseMode = readInit( line );
421  }
422  }
423 
424  /*
425  cout << " innerRead: " <<
426  lineNum_ << " lines read, " <<
427  numCompartments_ << " compartments, " <<
428  numPools_ << " molecules, " <<
429  numReacs_ << " reacs, " <<
430  numEnz_ << " enzs, " <<
431  numMMenz_ << " MM enzs, " <<
432  numOthers_ << " others," <<
433  numPlot_ << " plots," <<
434  " PlotDt = " << plotdt_ <<
435  endl;
436  */
437 }
438 
440 {
441  vector< string > argv;
442  chopLine( line, argv );
443  if ( argv.size() < 3 )
444  return INIT;
445 
446  if ( argv[0] == "FASTDT" ) {
447  fastdt_ = atof( argv[2].c_str() );
448  return INIT;
449  }
450  if ( argv[0] == "SIMDT" ) {
451  simdt_ = atof( argv[2].c_str() );
452  return INIT;
453  }
454  if ( argv[0] == "CONTROLDT" ) {
455  controldt_ = atof( argv[2].c_str() );
456  return INIT;
457  }
458  if ( argv[0] == "PLOTDT" ) {
459  plotdt_ = atof( argv[2].c_str() );
460  return INIT;
461  }
462  if ( argv[0] == "MAXTIME" ) {
463  maxtime_ = atof( argv[2].c_str() );
464  return INIT;
465  }
466  if ( argv[0] == "TRANSIENT_TIME" ) {
467  transientTime_ = atof( argv[2].c_str() );
468  return INIT;
469  }
470  if ( argv[0] == "VARIABLE_DT_FLAG" ) {
471  useVariableDt_ = atoi( argv[2].c_str() );
472  return INIT;
473  }
474  if ( argv[0] == "DEFAULT_VOL" ) {
475  defaultVol_ = atof( argv[2].c_str() );
476  return INIT;
477  }
478  if ( argv[0] == "VERSION" ) {
479  version_ = atoi( argv[2].c_str() );
480  return INIT;
481  }
482 
483  if ( argv[0] == "initdump" ) {
484  initdumpVersion_ = atoi( argv[2].c_str() );
485  return DATA;
486  }
487  return INIT;
488 }
489 
490 
491 void ReadKkit::readData( const string& line )
492 {
493  vector< string > argv;
494  chopLine( line, argv );
495 
496  if ( argv[0] == "simundump" )
497  undump( argv );
498  else if ( argv[0] == "addmsg" )
499  addmsg( argv );
500  else if ( argv[0] == "call" )
501  call( argv );
502  else if ( argv[0] == "simobjdump" )
503  objdump( argv );
504  else if ( argv[0] == "xtextload" )
505  textload( argv );
506  else if ( argv[0] == "loadtab" )
507  loadTab( argv );
508 }
509 
510 string ReadKkit::pathTail( const string& path, string& head ) const
511 {
512  string::size_type pos = path.find_last_of( "/" );
513  assert( pos != string::npos );
514 
515  head = basePath_ + path.substr( 0, pos );
516  return path.substr( pos + 1 );
517 }
518 
519 string ReadKkit::cleanPath( const string& path ) const
520 {
521  // Could surely do this better with STL. But harder to understand.
522  // Harsha: Cleaned up this function
523  // minus was getting replaced with underscore, but in some genesis model
524  // pool and reaction/Enzyme has same string name with
525  // difference of minus and underscore like eIF4G_A-clx and eIF4G_A_clx,
526  // which later created a problem as the same name exist in moose when minus
527  // was replaced with underscore.
528  //So replacing minus with _minus_ like I do in SBML
529  size_t Iindex = 0;
530  string cleanDigit="/";
531  while(true)
532  {
533  size_t sindex = path.find('/',Iindex+1);
534  if (sindex == string::npos)
535  { if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0]) )
536  cleanDigit += '_' ;
537  cleanDigit += path.substr(Iindex+1,sindex-Iindex-1);
538  break;
539  }
540  if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0]))
541  cleanDigit+='_';
542  cleanDigit += path.substr(Iindex+1,sindex-Iindex);
543  Iindex = sindex;
544  }
545  string ret = cleanDigit;
546  //string ret = path;
547  string cleanString;
548  for ( unsigned int i = 0; i < cleanDigit.length(); ++i ) {
549  char c = ret[i];
550  if ( c == '*' )
551  cleanString += "_p";
552  else if ( c == '[' || c == ']' || c == '@' || c == ' ')
553  cleanString += '_';
554  else if (c == '-')
555  cleanString += "_";
556  else
557  cleanString += c;
558  }
559  return cleanString;
560 }
561 
562 void assignArgs( map< string, int >& argConv, const vector< string >& args )
563 {
564  for ( unsigned int i = 2; i != args.size(); ++i )
565  argConv[ args[i] ] = i + 2;
566 }
567 
568 void ReadKkit::objdump( const vector< string >& args)
569 { if ( args[1] == "kpool" )
570  assignArgs( poolMap_, args );
571  else if ( args[1] == "kreac" )
572  assignArgs( reacMap_, args );
573  else if ( args[1] == "kenz" )
574  assignArgs( enzMap_, args );
575  else if ( args[1] == "group" )
576  assignArgs( groupMap_, args );
577  else if ( args[1] == "xtab" )
578  assignArgs( tableMap_, args );
579  else if ( args[1] == "stim" )
580  assignArgs( stimMap_, args );
581  else if ( args[1] == "kchan" )
582  assignArgs( chanMap_, args );
583 }
584 
585 void ReadKkit::call( const vector< string >& args)
586 {
588  if ( args.size() > 3 ) {
589  unsigned int len = args[1].length();
590  if ( ( args[1].substr( len - 5 ) == "notes" ) &&
591  args[2] == "LOAD" ) {
592  if ( args[3].length() == 0 )
593  return;
594  //HARSHA: Added CleanPath.
595  string objName = cleanPath(args[1].substr( 0, len - 5 ));
596  Id test(basePath_+objName);
597  Id obj( basePath_ + objName + "info" );
598  if ( obj != Id() ) {
599  string notes = "";
600  string space = "";
601  for ( unsigned int i = 3; i < args.size(); ++i ) {
602  unsigned int innerLength = args[i].length();
603  if ( innerLength == 0 )
604  continue;
605  unsigned int start = 0;
606  unsigned int end = innerLength;
607  if ( args[i][0] == '\"' )
608  start = 1;
609  if ( args[i][innerLength - 1] == '\"' )
610  end = innerLength - 1 - start;
611 
612  notes += space + args[i].substr( start, end );
613  space = " ";
614  }
615  Field< string >::set( obj, "notes", notes );
616  }
617  }
618  }
619 }
620 
621 void ReadKkit::textload( const vector< string >& args)
622 {
623 }
624 
625 void ReadKkit::undump( const vector< string >& args)
626 { if ( args[1] == "kpool" )
627  buildPool( args );
628  else if ( args[1] == "kreac" )
629  buildReac( args );
630  else if ( args[1] == "kenz" )
631  buildEnz( args );
632  else if ( args[1] == "text" )
633  buildText( args );
634  else if ( args[1] == "xplot" )
635  buildPlot( args );
636  else if ( args[1] == "xgraph" )
637  buildGraph( args );
638  else if ( args[1] == "group" )
639  buildGroup( args );
640  else if ( args[1] == "geometry" )
641  buildGeometry( args );
642  else if ( args[1] == "stim" )
643  buildStim( args );
644  else if ( args[1] == "xcoredraw" )
645  ;
646  else if ( args[1] == "xtree" )
647  ;
648  else if ( args[1] == "xtext" )
649  ;
650  else if ( args[1] == "doqcsinfo" )
651  ;
652  else if ( args[1] == "kchan" )
653  buildChan( args );
654  else if ( args[1] == "xtab" )
655  buildTable( args );
656  else
657  cout << "ReadKkit::undump: Do not know how to build '" << args[1] <<
658  "'\n";
659 }
660 
661 Id ReadKkit::buildCompartment( const vector< string >& args )
662 {
663  Id compt;
665  return compt;
666 }
667 
668 Id ReadKkit::buildReac( const vector< string >& args )
669 {
670  string head;
671  string clean = cleanPath( args[2] );
672  string tail = pathTail( clean, head );
673  Id pa = shell_->doFind( head ).id;
674  assert( pa != Id() );
675 
676  double kf = atof( args[ reacMap_[ "kf" ] ].c_str() );
677  double kb = atof( args[ reacMap_[ "kb" ] ].c_str() );
678 
679  // We have a slight problem because MOOSE has a more precise value for
680  // NA than does kkit. Here we assume that the conc units from Kkit are
681  // meant to be OK, so they override the #/cell (lower case k) units.
682  // So we convert all the Kfs and Kbs in the entire system after
683  // the model has been created, once we know the order of each reac.
684 
685  Id reac = shell_->doCreate( "Reac", pa, tail, 1 );
686  reacIds_[ clean.substr( 10 ) ] = reac;
687  // Here is another hack: The native values stored in the reac are
688  // Kf and Kb, in conc units. However the 'clean' values from kkit
689  // are the number values numKf and numKb. In the
690  // function convertReacRatesToNumUnits we take the numKf and numKb and
691  // do proper conc scaling.
692  Field< double >::set( reac, "Kf", kf );
693  Field< double >::set( reac, "Kb", kb );
694 
695  Id info = buildInfo( reac, reacMap_, args );
696  numReacs_++;
697  return reac;
698 }
699 
700 void ReadKkit::separateVols( Id pool, double vol )
701 {
702  static const double TINY = 1e-3;
703 
704  for ( unsigned int i = 0 ; i < vols_.size(); ++i ) {
705  if ( fabs( vols_[i] - vol ) / ( fabs( vols_[i] ) + fabs( vol ) ) < TINY ) {
706  volCategories_[i].push_back( pool );
707  return;
708  }
709  }
710  vols_.push_back( vol );
711  vector< Id > temp( 1, pool );
712  volCategories_.push_back( temp );
713 }
714 
716  const pair< unsigned int, double >& A,
717  const pair< unsigned int, double >& B )
718 {
719  return A.second < B.second;
720 }
721 // Returns the ranking of each volume. Largest is 0. This would be the
722 // suffix to attach to the compartment name.
723 vector< unsigned int > findVolOrder( const vector< double >& vols )
724 {
725  vector< pair< unsigned int, double > > p( vols.size() );
726  for ( unsigned int i = 0; i < vols.size(); ++i ) {
727  p[i].first = i;
728  p[i].second = vols[i];
729  }
730  sort( p.begin(), p.end(), volCompare );
731  vector< unsigned int > ret( vols.size() );
732  for ( unsigned int i = 0; i < vols.size(); ++i ) {
733  ret[ vols.size() -i -1 ] = p[i].first;
734  }
735  return ret;
736 }
737 
738 // We assume that the biggest compartment contains all the rest.
739 // This is not true in synapses, where they are adjacent.
741 {
742  Id kinetics = Neutral::child( baseId_.eref(), "kinetics" );
743  assert( kinetics != Id() );
744  vector< unsigned int > volOrder = findVolOrder( vols_ );
745  assert( volCategories_.size() == vols_.size() );
746  assert( volCategories_.size() == volOrder.size() );
747 
748  for ( unsigned int j = 0 ; j < volOrder.size(); ++j ) {
749  unsigned int i = volOrder[j];
750  if ( vols_[i] < 0 ) // Special case for enz complexes: vol == -1.
751  continue;
752  string name;
753  Id kinId = Neutral::child( baseId_.eref(), "kinetics" );
754  assert( kinId != Id() );
755  Id comptId;
756  // if ( i == maxi )
757  if ( j == 0 ) {
758  comptId = kinId;
759  } else {
760  stringstream ss;
761  ss << "compartment_" << j;
762  name = ss.str();
763  comptId = Neutral::child( baseId_.eref(), name );
764  if ( comptId == Id() )
765  comptId = shell_->doCreate( "CubeMesh", baseId_, name, 1 );
766  }
767  SetGet1< double >::set( comptId, "setVolumeNotRates",vols_[i]);
768  /*
769  if ( comptId.element()->cinfo()->isA( "CubeMesh" ) ) {
770  double side = pow( vols_[i], 1.0 / 3.0 );
771  vector< double > coords( 9, side );
772  coords[0] = coords[1] = coords[2] = 0;
773  // Field< double >::set( comptId, "volume", vols_[i] );
774  Field< vector< double > >::set( comptId, "coords", coords );
775  } else {
776  }
777  */
778  // compartments_.push_back( comptId );
779  for ( vector< Id >::iterator k = volCategories_[i].begin();
780  k != volCategories_[i].end(); ++k ) {
781  // if ( moveOntoCompartment_ ) {
782  if ( ! (getCompt( *k ).id == comptId ) )
783  shell_->doMove( *k, comptId );
784  // }
785  }
786  }
787 }
788 
790 {
791  static const Finfo* subFinfo =
792  ReacBase::initCinfo()->findFinfo( "subOut" );
793  assert( subFinfo );
794 
795  vector< Id > subVec;
796  reac.element()->getNeighbors( subVec, subFinfo );
797  if ( subVec.size() == 0 ) // Dangling reaction
798  return Id();
799  // For now just put the reac in the compt belonging to the
800  // first substrate
801  return getCompt( subVec[0] );
802 }
803 
811 {
812  for ( map< string, Id >::iterator i = reacIds_.begin();
813  i != reacIds_.end(); ++i ) {
814  Id compt = findParentComptOfReac( i->second );
815  if ( compt != Id() ) {
816  if ( ! (getCompt( i->second ).id == compt ) )
817  shell_->doMove( i->second, compt );
818  }
819  }
820 }
821 
822 
829 {
830  static const Finfo* enzFinfo =
831  EnzBase::initCinfo()->findFinfo( "enzOut" );
832  assert( enzFinfo );
833 
834  vector< Id > enzVec;
835  enz.element()->getNeighbors( enzVec, enzFinfo );
836  assert( enzVec.size() == 1 );
837  vector< Id > meshEntries;
838  return getCompt( enzVec[0] );
839 }
840 
848 {
849  /*
850  Should not be needed, because the parent pool will move.
851  for ( map< string, Id >::iterator i = enzIds_.begin();
852  i != enzIds_.end(); ++i ) {
853  Id compt = getCompt( Neutral::parent( i->second ).id );
854  if ( moveOntoCompartment_ ) {
855  if ( ! (getCompt( i->second ).id == compt ) )
856  shell_->doMove( i->second, compt );
857  }
858  }
859  */
860 }
861 
869 {
870  /*
871  Should not be needed, because the parent pool will move.
872  for ( map< string, Id >::iterator i = mmEnzIds_.begin();
873  i != mmEnzIds_.end(); ++i ) {
874  Id compt = getCompt( Neutral::parent( i->second ).id );
875  if ( moveOntoCompartment_ ) {
876  if ( ! (getCompt( i->second ).id == compt ) )
877  shell_->doMove( i->second, compt );
878  }
879  }
880  */
881 }
882 
883 Id ReadKkit::buildEnz( const vector< string >& args )
884 {
885  string head;
886  string clean = cleanPath( args[2] );
887  string tail = pathTail( clean, head );
888  Id pa = shell_->doFind( head ).id;
889  assert ( pa != Id() );
890 
891  double k1 = atof( args[ enzMap_[ "k1" ] ].c_str() );
892  double k2 = atof( args[ enzMap_[ "k2" ] ].c_str() );
893  double k3 = atof( args[ enzMap_[ "k3" ] ].c_str() );
894  // double volscale = atof( args[ enzMap_[ "vol" ] ].c_str() );
895  double nComplexInit =
896  atof( args[ enzMap_[ "nComplexInit" ] ].c_str() );
897  // double vol = atof( args[ enzMap_[ "vol" ] ].c_str());
898  bool isMM = atoi( args[ enzMap_[ "usecomplex" ] ].c_str());
899  assert( poolVols_.find( pa ) != poolVols_.end() );
900  double vol = poolVols_[ pa ];
901 
909  if ( isMM ) {
910  Id enz = shell_->doCreate( "MMenz", pa, tail, 1 );
911  assert( enz != Id () );
912  string mmEnzPath = clean.substr( 10 );
913  mmEnzIds_[ mmEnzPath ] = enz;
914 
915  assert( k1 > EPSILON );
916  double Km = ( k2 + k3 ) / k1;
917 
918  Field< double >::set( enz, "Km", Km );
919  Field< double >::set( enz, "kcat", k3 );
920  Id info = buildInfo( enz, enzMap_, args );
921  numMMenz_++;
922  return enz;
923  } else {
924  Id enz = shell_->doCreate( "Enz", pa, tail, 1 );
925  // double parentVol = Field< double >::get( pa, "volume" );
926  assert( enz != Id () );
927  string enzPath = clean.substr( 10 );
928  enzIds_[ enzPath ] = enz;
929 
930  // Need to figure out what to do about these. Perhaps it is OK
931  // to do this assignments in raw #/cell units.
932  Field< double >::set( enz, "k3", k3 );
933  Field< double >::set( enz, "k2", k2 );
934  // Here we explicitly calculate Km because the substrates are
935  // not set up till later, and without them the volume calculations
936  // are confused.
937  double volScale = lookupVolumeFromMesh(pa.eref());
938  double Km = (k2+k3)/(k1 * KKIT_NA * vol ); // Scaling for uM to mM.
939  SetGet2< double, double >::set( enz, "setKmK1", Km, k1 );
940 
941  string cplxName = tail + "_cplx";
942  string cplxPath = enzPath + "/" + cplxName;
943  Id cplx = shell_->doCreate( "Pool", enz, cplxName, 1 );
944  assert( cplx != Id () );
945  poolIds_[ cplxPath ] = cplx;
946  // Field< double >::set( cplx, "nInit", nComplexInit );
947  Field< double >::set( cplx, "nInit", nComplexInit );
948 
949  // Use this later to assign mesh entries to enz cplx.
950  enzCplxMols_.push_back( pair< Id, Id >( pa, cplx ) );
951  separateVols( cplx, -1 ); // -1 vol is a flag to defer mesh assignment for the cplx pool.
952 
953  ObjId ret = shell_->doAddMsg( "OneToAll",
954  ObjId( enz, 0 ), "cplx",
955  ObjId( cplx, 0 ), "reac" );
956  assert( ret != ObjId() );
957 
958 
959  // cplx()->showFields();
960  // enz()->showFields();
961  // pa()->showFields();
962  Id info = buildInfo( enz, enzMap_, args );
963  numEnz_++;
964  return enz;
965  }
966 }
967 
968 Id ReadKkit::buildText( const vector< string >& args )
969 {
970  Id text;
971  numOthers_++;
972  return text;
973 }
974 
976  map< string, int >& m, const vector< string >& args )
977 {
978  Id info = shell_->doCreate( "Annotator", parent, "info", 1 );
979  assert( info != Id() );
980 
981  double x = atof( args[ m[ "x" ] ].c_str() );
982  double y = atof( args[ m[ "y" ] ].c_str() );
983 
984  Field< double >::set( info, "x", x );
985  Field< double >::set( info, "y", y );
986  Field< string >::set( info, "color", args[ m[ "xtree_fg_req" ] ] );
987  Field< string >::set( info, "textColor",
988  args[ m[ "xtree_textfg_req" ] ] );
989  return info;
990 }
991 
992 Id ReadKkit::buildGroup( const vector< string >& args )
993 {
994  string head;
995  string tail = pathTail( cleanPath( args[2] ), head );
996  Id pa = shell_->doFind( head ).id;
997  assert( pa != Id() );
998  Id group = shell_->doCreate( "Neutral", pa, tail, 1 );
999  assert( group != Id() );
1000  Id info = buildInfo( group, groupMap_, args );
1001 
1002  numOthers_++;
1003  return group;
1004 }
1005 
1015 Id ReadKkit::buildPool( const vector< string >& args )
1016 {
1017  string head;
1018  string clean = cleanPath( args[2] );
1019  string tail = pathTail( clean, head );
1020  Id pa = shell_->doFind( head ).id;
1021  assert( pa != Id() );
1022 
1023  double nInit = atof( args[ poolMap_[ "nInit" ] ].c_str() );
1024  double vsf = atof( args[ poolMap_[ "vol" ] ].c_str() );
1031  double vol = 1.0e3 * vsf / KKIT_NA; // Converts volscale to actual vol in m^3
1032  int slaveEnable = atoi( args[ poolMap_[ "slave_enable" ] ].c_str() );
1033  double diffConst = atof( args[ poolMap_[ "DiffConst" ] ].c_str() );
1034 
1035  // I used -ve D as a flag to replace pool-specific D
1036  // with the global value of D. Here we just ignore it.
1037  if ( diffConst < 0 )
1038  diffConst = 0;
1039 
1040  Id pool;
1041  if ( slaveEnable == 0 ) {
1042  pool = shell_->doCreate( "Pool", pa, tail, 1 );
1043  } else if ( slaveEnable & 4 ) {
1044  pool = shell_->doCreate( "BufPool", pa, tail, 1 );
1045  } else {
1046  pool = shell_->doCreate( "Pool", pa, tail, 1 );
1047  /*
1048  cout << "ReadKkit::buildPool: Unknown slave_enable flag '" <<
1049  slaveEnable << "' on " << clean << "\n";
1050  */
1051  poolFlags_[pool] = slaveEnable;
1052  }
1053  assert( pool != Id() );
1054  // skip the 10 chars of "/kinetics/"
1055  poolIds_[ clean.substr( 10 ) ] = pool;
1056 
1057  Field< double >::set( pool, "nInit", nInit );
1058  Field< double >::set( pool, "diffConst", diffConst );
1059  // SetGet1< double >::set( pool, "setVolume", vol );
1060  separateVols( pool, vol );
1061  poolVols_[pool] = vol;
1062 
1063  Id info = buildInfo( pool, poolMap_, args );
1064  /*
1065  cout << setw( 20 ) << head << setw( 15 ) << tail << " " <<
1066  setw( 12 ) << nInit << " " <<
1067  vol << " " << diffConst << " " <<
1068  slaveEnable << endl;
1069  */
1070  numPools_++;
1071  return pool;
1072 }
1073 
1078 Id ReadKkit::findSumTotSrc( const string& src )
1079 {
1080  map< string, Id >::iterator i = poolIds_.find( src );
1081  if ( i != poolIds_.end() ) {
1082  return i->second;
1083  }
1084  i = enzIds_.find( src );
1085  if ( i != enzIds_.end() ) {
1086  string head;
1087  string cplx = src + '/' + pathTail( src, head ) + "_cplx";
1088  i = poolIds_.find( cplx );
1089  if ( i != poolIds_.end() ) {
1090  return i->second;
1091  }
1092  }
1093  cout << "Error: ReadKkit::findSumTotSrc: Cannot find source pool '" << src << endl;
1094  assert( 0 );
1095  return Id();
1096 }
1097 
1098 void ReadKkit::buildSumTotal( const string& src, const string& dest )
1099 {
1100  map< string, Id >::iterator i = poolIds_.find( dest );
1101  assert( i != poolIds_.end() );
1102  Id destId = i->second;
1103 
1104  Id sumId;
1105  // Check if the pool has not yet been converted to handle SumTots.
1106  if ( destId.element()->cinfo()->name() == "Pool" ) {
1107  sumId = shell_->doCreate( "Function", destId, "func", 1 );
1108  // Turn dest into a FuncPool.
1109  destId.element()->zombieSwap( BufPool::initCinfo() );
1110 
1111  ObjId ret = shell_->doAddMsg( "single",
1112  ObjId( sumId, 0 ), "valueOut",
1113  ObjId( destId, 0 ), "setN" );
1114  assert( ret != ObjId() );
1115  } else {
1116  sumId = Neutral::child( destId.eref(), "func" );
1117  }
1118 
1119  if ( sumId == Id() ) {
1120  cout << "Error: ReadKkit::buildSumTotal: could not make Function on '"
1121  << dest << "'\n";
1122  return;
1123  }
1124 
1125  Id srcId = findSumTotSrc( src );
1126  unsigned int numVars = Field< unsigned int >::get( sumId, "numVars" );
1127  ObjId xi( sumId.value() + 1, 0, numVars );
1128  Field< unsigned int >::set( sumId, "numVars", numVars + 1 );
1129 
1130  ObjId ret = shell_->doAddMsg( "single",
1131  ObjId( srcId, 0 ), "nOut",
1132  xi, "input" );
1133  assert( ret != ObjId() );
1134 
1135 
1136  stringstream ss;
1137  for ( unsigned int i = 0; i < numVars; ++i ) {
1138  ss << "x" << i << "+";
1139  }
1140  ss << "x" << numVars;
1141  Field< string >::set( sumId, "expr", ss.str() );
1142 }
1143 
1147 Id ReadKkit::buildStim( const vector< string >& args )
1148 {
1149  string head;
1150  string clean = cleanPath( args[2] );
1151  string tail = pathTail( clean, head );
1152  Id pa = shell_->doFind( head ).id;
1153  assert( pa != Id() );
1154 
1155  double level1 = atof( args[ stimMap_[ "firstLevel" ] ].c_str() );
1156  double width1 = atof( args[ stimMap_[ "firstWidth" ] ].c_str() );
1157  double delay1 = atof( args[ stimMap_[ "firstDelay" ] ].c_str() );
1158  double level2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() );
1159  double width2 = atof( args[ stimMap_[ "secondWidth" ] ].c_str() );
1160  double delay2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() );
1161  double baselevel = atof( args[ stimMap_[ "baseLevel" ] ].c_str() );
1162 
1163  Id stim = shell_->doCreate( "PulseGen", pa, tail, 1 );
1164  assert( stim != Id() );
1165  string stimPath = clean.substr( 10 );
1166  stimIds_[ stimPath ] = stim;
1167  Field< double >::set( stim, "firstLevel", level1 );
1168  Field< double >::set( stim, "firstWidth", width1 );
1169  Field< double >::set( stim, "firstDelay", delay1 );
1170  Field< double >::set( stim, "secondLevel", level2 );
1171  Field< double >::set( stim, "secondWidth", width2 );
1172  Field< double >::set( stim, "secondDelay", delay2 );
1173  Field< double >::set( stim, "baseLevel", baselevel );
1174 
1175  numStim_++;
1176  return stim;
1177 }
1178 
1182 Id ReadKkit::buildChan( const vector< string >& args )
1183 {
1184  string head;
1185  string clean = cleanPath( args[2] );
1186  string tail = pathTail( clean, head );
1187  Id pa = shell_->doFind( head ).id;
1188  assert( pa != Id() );
1189 
1190  // cout << "Warning: Kchan not yet supported in MOOSE, creating dummy:\n" << " " << clean << "\n";
1191  //
1192  double permeability = atof( args[ chanMap_["perm"] ].c_str() );
1193  Id chan = shell_->doCreate( "ConcChan", pa, tail, 1 );
1194  Field< double >::set( chan, "permeability", permeability );
1195  assert( chan != Id() );
1196  string chanPath = clean.substr( 10 );
1197  chanIds_[ chanPath ] = chan;
1198  return chan;
1199 }
1200 
1201 
1202 Id ReadKkit::buildGeometry( const vector< string >& args )
1203 {
1204  Id geometry;
1205  numOthers_++;
1206  return geometry;
1207 }
1208 
1209 Id ReadKkit::buildGraph( const vector< string >& args )
1210 {
1211  string head;
1212  string tail = pathTail( cleanPath( args[2] ), head );
1213 
1214  Id pa = shell_->doFind( head ).id;
1215  assert( pa != Id() );
1216  Id graph = shell_->doCreate( "Neutral", pa, tail, 1 );
1217  assert( graph != Id() );
1218  numOthers_++;
1219  return graph;
1220 }
1221 
1222 Id ReadKkit::buildPlot( const vector< string >& args )
1223 {
1224  string head;
1225  string tail = pathTail( cleanPath( args[2] ), head ); // Name of plot
1226  string temp;
1227  string graph = pathTail( head, temp ); // Name of graph
1228 
1229  Id pa = shell_->doFind( head ).id;
1230  assert( pa != Id() );
1231 
1232  Id plot = shell_->doCreate( "Table2", pa, tail, 1 );
1233  assert( plot != Id() );
1234 
1235  temp = graph + "/" + tail;
1236  plotIds_[ temp ] = plot;
1237 
1238  numPlot_++;
1239  return plot;
1240 }
1241 
1244 
1245 Id ReadKkit::buildTable( const vector< string >& args )
1246 {
1247  string head;
1248  string clean = cleanPath( args[2] );
1249  string tail = pathTail( clean, head ); // Name of xtab
1250 
1251  Id pa = shell_->doFind( head ).id;
1252  assert( pa != Id() );
1253  Id tab;
1254 
1255  int mode = atoi( args[ tableMap_[ "step_mode" ] ].c_str() );
1256  if ( mode == TAB_IO ) {
1257  } else if ( mode == TAB_LOOP || mode == TAB_ONCE ) {
1258  tab = shell_->doCreate( "StimulusTable", pa, tail, 1 );
1259  assert( tab != Id() );
1260  double stepSize = atof( args[ tableMap_[ "stepsize" ] ].c_str() );
1261  Field< double >::set( tab, "stepSize", stepSize );
1262  if ( mode == TAB_LOOP )
1263  Field< bool >::set( tab, "doLoop", 1 );
1264  double input = atof( args[ tableMap_[ "input" ] ].c_str() );
1265  Field< double >::set( tab, "startTime", -input );
1266  // The other StimulusTable parameters will have to wait till the
1267  // loadTab is invoked.
1268  }
1269 
1270 
1271  string temp = clean.substr( 10 );
1272  tabIds_[ temp ] = tab;
1273 
1274  Id info = buildInfo( tab, tableMap_, args );
1275 
1276  return tab;
1277 }
1278 
1279 unsigned int ReadKkit::loadTab( const vector< string >& args )
1280 {
1281  Id tab;
1282  unsigned int start = 0;
1283  if ( args[1].substr( 0, 5 ) == "-cont" || args[1] == "-end" ) {
1284  start = 2;
1285  tab = lastTab_;
1286  assert( tab != Id() );
1287  } else {
1288  tabEntries_.resize( 0 );
1289  start = 7;
1290  assert( args.size() >= start );
1291  lastTab_ = tab = Id( basePath_ + args[1] );
1292  assert( tab != Id() );
1293  // int calc_mode = atoi( args[3].c_str() );
1294  // int xdivs = atoi( args[4].c_str() );
1295  if ( tab.element()->cinfo()->isA( "StimulusTable" ) ) {
1296  double xmin = atof( args[5].c_str() );
1297  double xmax = atof( args[6].c_str() );
1298  double start = Field< double >::get( tab, "startTime" );
1299  start += xmin;
1300  Field< double >::set( tab, "startTime", start );
1301  Field< double >::set( tab, "stopTime", xmax );
1302  }
1303  }
1304 
1305  for ( unsigned int i = start; i < args.size(); ++i ) {
1306  tabEntries_.push_back( atof( args[i].c_str() ) );
1307  }
1308  Field< vector< double > >::set( tab, "vector", tabEntries_ );
1309 
1310  // cout << "Loading table for " << args[0] << "," << args[1] << "," << clean << endl;
1311 
1312  if ( args[1] == "-end" )
1313  lastTab_ = Id();
1314 
1315  return 0;
1316 }
1317 
1319  const string& src, const map< string, Id >& m1, const string& srcMsg,
1320  const string& dest, const map< string, Id >& m2, const string& destMsg,
1321  bool isBackward )
1322 {
1323  map< string, Id >::const_iterator i = m1.find( src );
1324  assert( i != m1.end() );
1325  Id srcId = i->second;
1326 
1327  i = m2.find( dest );
1328  assert( i != m2.end() );
1329  Id destId = i->second;
1330 
1331  // dest pool is substrate of src reac
1332  if ( isBackward ) {
1333  ObjId ret = shell_->doAddMsg( "AllToOne",
1334  ObjId( srcId, 0 ), srcMsg,
1335  ObjId( destId, 0 ), destMsg );
1336  assert( ret != ObjId() );
1337  } else {
1338  ObjId ret = shell_->doAddMsg( "OneToAll",
1339  ObjId( srcId, 0 ), srcMsg,
1340  ObjId( destId, 0 ), destMsg );
1341  assert( ret != ObjId() );
1342  }
1343 }
1344 
1345 
1346 void ReadKkit::addmsg( const vector< string >& args)
1347 {
1348  string src = cleanPath( args[1] ).substr( 10 );
1349  string dest = cleanPath( args[2] ).substr( 10 );
1350 
1351  if ( args[3] == "REAC" ) {
1352  if ( args[4] == "A" && args[5] == "B" ) {
1353  if ( chanIds_.find( src ) != chanIds_.end() )
1354  innerAddMsg( src, chanIds_, "in", dest, poolIds_, "reac");
1355  else
1356  innerAddMsg( src, reacIds_, "sub", dest, poolIds_, "reac");
1357  }
1358  else if ( args[4] == "B" && args[5] == "A" ) {
1359  if ( chanIds_.find( src ) != chanIds_.end() )
1360  innerAddMsg( src, chanIds_, "out", dest, poolIds_, "reac");
1361  else
1362  // dest pool is product of src reac
1363  innerAddMsg( src, reacIds_, "prd", dest, poolIds_, "reac");
1364  }
1365  else if ( args[4] == "sA" && args[5] == "B" ) {
1366  // Msg from enzyme to substrate.
1367  if ( mmEnzIds_.find( src ) == mmEnzIds_.end() )
1368  innerAddMsg( src, enzIds_, "sub", dest, poolIds_, "reac" );
1369  else
1370  innerAddMsg( src, mmEnzIds_, "sub", dest, poolIds_, "reac" );
1371  }
1372  }
1373  else if ( args[3] == "ENZYME" ) { // Msg from enz pool to enz site
1374  if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() )
1375  innerAddMsg( dest, enzIds_, "enz", src, poolIds_, "reac" );
1376  else
1377  innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enzDest", 1);
1378  // innerAddMsg( dest, mmEnzIds_, "enz", src, poolIds_, "nOut", 1);
1379  /*
1380  if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() )
1381  innerAddMsg( src, poolIds_, "reac", dest, enzIds_, "enz" );
1382  else
1383  innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enz" );
1384  */
1385  }
1386  else if ( args[3] == "MM_PRD" ) { // Msg from enz to Prd pool
1387  if ( mmEnzIds_.find( src ) == mmEnzIds_.end() )
1388  innerAddMsg( src, enzIds_, "prd", dest, poolIds_, "reac" );
1389  else
1390  innerAddMsg( src, mmEnzIds_, "prd", dest, poolIds_, "reac" );
1391  }
1392  else if ( args[3] == "NUMCHAN" ) { // Msg from chan pool to concchan
1393  if ( chanIds_.find( dest ) != chanIds_.end() )
1394  innerAddMsg( src, poolIds_, "nOut", dest, chanIds_, "setNumChan");
1395  }
1396  else if ( args[3] == "PLOT" ) { // Time-course output for pool
1397  string head;
1398  string temp;
1399  dest = pathTail( cleanPath( args[2] ), head );
1400  string graph = pathTail( head, temp );
1401  temp = graph + "/" + dest;
1402  map< string, Id >::const_iterator i = plotIds_.find( temp );
1403  assert( i != plotIds_.end() );
1404  Id plot = i->second;
1405 
1406  i = poolIds_.find( src );
1407  Id pool;
1408  if ( i == poolIds_.end() ) {
1409  i = enzIds_.find( src ); // might be plotting an enzCplx.
1410  if ( i == enzIds_.end() ) {
1411  cout << "Error: ReadKkit: Unable to find src for plot: " <<
1412  src << ", " << dest << endl;
1413  assert( 0 );
1414  return;
1415  }
1416  vector< Id > enzcplx;
1417  i->second.element()->getNeighbors( enzcplx,
1418  i->second.element()->cinfo()->findFinfo( "cplxOut" ) );
1419  assert( enzcplx.size() == 1 );
1420  pool = enzcplx[0];
1421  } else {
1422  pool = i->second;
1423  }
1424 
1425  if ( args[4] == "Co" || args[4] == "CoComplex" ) {
1426  ObjId ret = shell_->doAddMsg( "Single",
1427  plot, "requestOut", pool, "getConc" );
1428  assert( ret != ObjId() );
1429  } else if ( args[4] == "n" || args[4] == "nComplex") {
1430  ObjId ret = shell_->doAddMsg( "Single",
1431  plot, "requestOut", pool, "getN" );
1432  assert( ret != ObjId() );
1433  } else {
1434  cout << "Unknown PLOT msg field '" << args[4] << "'\n";
1435  }
1436  }
1437  else if ( args[3] == "SUMTOTAL" ) { // Summation function.
1438  buildSumTotal( src, dest );
1439  }
1440  else if ( args[3] == "SLAVE" ) { // Summation function.
1441  if ( args[4] == "output" ) {
1442  setupSlaveMsg( src, dest );
1443  }
1444  }
1445 }
1446 
1447 void ReadKkit::setupSlaveMsg( const string& src, const string& dest )
1448 {
1449  // Convert the pool to a BufPool, if it isn't one already
1450  Id destId( basePath_ + "/kinetics/" + dest );
1451  assert( destId != Id() );
1452 
1453  if( !destId.element()->cinfo()->isA( "BufPool" )) {
1454  destId.element()->zombieSwap( BufPool::initCinfo() );
1455  }
1456 
1457  map< string, Id >* nameMap;
1458  // Check if the src is a table or a stim
1459  Id srcId( basePath_ + "/kinetics/" + src );
1460  assert( srcId != Id() );
1461  string output = "output";
1462  if ( srcId.element()->cinfo()->isA( "TableBase" ) ) {
1463  nameMap = &tabIds_;
1464  } else if ( srcId.element()->cinfo()->isA( "PulseGen" ) ) {
1465  nameMap = &stimIds_;
1466  output = "output";
1467  } else {
1468  cout << "Error: Unknown source for SLAVE msg: (" << src <<
1469  ", " << dest << ")\n";
1470  return;
1471  }
1472 
1473  // NSLAVE is 1, CONCSLAVE is 2.
1474  map< Id, int >::iterator i = poolFlags_.find( destId );
1475  if ( i == poolFlags_.end() || !( i->second & 2 ) ) {
1476  innerAddMsg( src, *nameMap, output, dest, poolIds_,
1477  "setNInit" );
1478  } else {
1479  innerAddMsg( src, *nameMap, output, dest, poolIds_,
1480  "setConcInit" );
1481 
1482  double CONCSCALE = 0.001;
1483  // Rescale from uM to millimolar.
1484  if ( nameMap == &tabIds_ ) {
1485  SetGet2< double, double >::set( srcId, "linearTransform",
1486  CONCSCALE, 0 );
1487  } else if ( nameMap == &stimIds_ ) {
1488  double x = Field< double >::get( srcId, "baseLevel" );
1489  Field< double >::set( srcId, "baseLevel", x * CONCSCALE );
1490  x = Field< double >::get( srcId, "firstLevel" );
1491  Field< double >::set( srcId, "firstLevel", x * CONCSCALE );
1492  x = Field< double >::get( srcId, "secondLevel" );
1493  Field< double >::set( srcId, "secondLevel", x * CONCSCALE );
1494  }
1495  }
1496  // cout << "Added slave msg from " << src << " to " << dest << endl;
1497 }
1498 
1499 // We have a slight problem because MOOSE has a more precise value for
1500 // NA than does kkit. Also, at the time the model is loaded, the volume
1501 // relationships are unknown. So we need to fix up conc units of all reacs.
1502 // Here we assume that the conc units from Kkit are
1503 // meant to be OK, so they override the #/cell (lower case k) units.
1504 // So we convert all the Kfs and Kbs in the entire system after
1505 // the model has been created, once we know the order of each reac.
1507 {
1512 }
1513 
1515 {
1516  const double NA_RATIO = KKIT_NA / NA;
1517  for ( map< string, Id >::iterator i = poolIds_.begin();
1518  i != poolIds_.end(); ++i ) {
1519  Id pool = i->second;
1520  double nInit = Field< double >::get( pool, "nInit" );
1521  double n = Field< double >::get( pool, "n" );
1522 
1523  nInit /= NA_RATIO;
1524  n /= NA_RATIO;
1525  Field< double >::set( pool, "nInit", nInit );
1526  Field< double >::set( pool, "n", n );
1527  }
1528 }
1529 
1531 {
1532  const double NA_RATIO = KKIT_NA / NA;
1533  for ( map< string, Id >::iterator i = reacIds_.begin();
1534  i != reacIds_.end(); ++i ) {
1535  Id reac = i->second;
1536  double kf = Field< double >::get( reac, "Kf" );
1537  double kb = Field< double >::get( reac, "Kb" );
1538  // Note funny access here, using the Conc unit term (Kf) to get the
1539  // num unit term (kf). When reading, there are no volumes so the
1540  // Kf gets assigned to what was the kf value from kkit.
1541 
1542  // At this point the kf and kb are off because the
1543  // NA for kkit is not accurate. So we correct for this.
1544  unsigned int numSub =
1545  Field< unsigned int >::get( reac, "numSubstrates" );
1546  unsigned int numPrd =
1547  Field< unsigned int >::get( reac, "numProducts" );
1548 
1549  if ( numSub > 1 )
1550  kf *= pow( NA_RATIO, numSub - 1.0 );
1551 
1552  if ( numPrd > 1 )
1553  kb *= pow( NA_RATIO, numPrd - 1.0 );
1554 
1555  // Now we have the correct numKf and numKb, plug them into the
1556  // reac, and let it internally fix up the Kf and Kb.
1557  Field< double >::set( reac, "numKf", kf );
1558  Field< double >::set( reac, "numKb", kb );
1559  }
1560 }
1561 
1563 {
1564  const double NA_RATIO = KKIT_NA / NA;
1565  for ( map< string, Id >::iterator i = mmEnzIds_.begin();
1566  i != mmEnzIds_.end(); ++i ) {
1567  Id enz = i->second;
1568  // This was set in the original # units.
1569  double numKm = Field< double >::get( enz, "Km" );
1570  // At this point the numKm is inaaccurate because the
1571  // NA for kkit is not accurate. So we correct for this.
1572  double numSub =
1573  Field< unsigned int >::get( enz, "numSubstrates" );
1574  // Note that we always have the enz itself as a substrate term.
1575  if ( numSub > 0 )
1576  numKm *= pow( NA_RATIO, -numSub );
1577 
1578  // Now we have the correct numKm, plug it into the MMenz, and
1579  // let it internally fix up the Km
1580  Field< double >::set( enz, "numKm", numKm );
1581  }
1582 }
1583 
1584 // we take k2 and k3 as correct, since those are just time^-1.
1585 // Here we just need to convert k1. Originally values were set as
1586 // k1, k2, k3 from the kkit file. k1 will need to change a bit because
1587 // of the NA and KKIT_NA discrepancy.
1589 {
1590  const double NA_RATIO = KKIT_NA / NA;
1591  for ( map< string, Id >::iterator i = enzIds_.begin();
1592  i != enzIds_.end(); ++i ) {
1593  Id enz = i->second;
1594  double k1 = Field< double >::get( enz, "k1" );
1595  // At this point the k1 is inaaccurate because the
1596  // NA for kkit is not accurate. So we correct for this.
1597  double numSub =
1598  Field< unsigned int >::get( enz, "numSubstrates" );
1599  // Note that we always have the enz itself as a substrate term.
1600  if ( numSub > 0 )
1601  k1 *= pow( NA_RATIO, numSub );
1602  Field< double >::set( enz, "k1", k1 );
1603  }
1604 }
Id findMeshOfEnz(Id enz)
Definition: ReadKkit.cpp:828
int wildcardFind(const string &path, vector< ObjId > &ret)
Definition: Wildcard.cpp:169
GenesisTableModes
Definition: ReadKkit.cpp:1242
Id buildGroup(const vector< string > &args)
Definition: ReadKkit.cpp:992
unsigned int version_
Default volume for new compartments.
Definition: ReadKkit.h:191
Id buildTable(const vector< string > &args)
Definition: ReadKkit.cpp:1245
void doStart(double runtime, bool notify=false)
Definition: Shell.cpp:332
void convertReacRatesToConcUnits()
Convert Reac rates, initially in n units.
Definition: ReadKkit.cpp:1530
void assignArgs(map< string, int > &argConv, const vector< string > &args)
Definition: ReadKkit.cpp:562
void undump(const vector< string > &args)
Definition: ReadKkit.cpp:625
vector< double > tabEntries_
This holds the vector of array entries for loadtab.
Definition: ReadKkit.h:242
char * data() const
Definition: Eref.cpp:41
double transientTime_
Simulation run time.
Definition: ReadKkit.h:188
double defaultVol_
Use both fast and sim dts.
Definition: ReadKkit.h:190
Id baseId_
Base path into which entire kkit model will go.
Definition: ReadKkit.h:181
void assignEnzCompartments()
Definition: ReadKkit.cpp:847
double maxtime_
Timestep for updating plots.
Definition: ReadKkit.h:187
unsigned int initdumpVersion_
KKit version.
Definition: ReadKkit.h:192
static SrcFinfo0 * group()
Definition: Group.cpp:17
char * data() const
Definition: ObjId.cpp:113
void readData(const string &line)
Definition: ReadKkit.cpp:491
double getMaxTime() const
Definition: ReadKkit.cpp:85
double fastdt_
Base Id onto which entire kkit model will go.
Definition: ReadKkit.h:183
const double NA
Definition: consts.cpp:15
void convertEnzRatesToConcUnits()
Definition: ReadKkit.cpp:1588
Id buildGeometry(const vector< string > &args)
Definition: ReadKkit.cpp:1202
map< string, int > stimMap_
Definition: ReadKkit.h:219
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
Id buildStim(const vector< string > &args)
Definition: ReadKkit.cpp:1147
bool volCompare(const pair< unsigned int, double > &A, const pair< unsigned int, double > &B)
Definition: ReadKkit.cpp:715
map< string, int > tableMap_
Definition: ReadKkit.h:218
void doSetClock(unsigned int tickNum, double dt)
Definition: Shell.cpp:377
void makeSolverOnCompt(Shell *s, const vector< ObjId > &compts, bool isGsolve)
Definition: ReadKkit.cpp:166
bool getMoveOntoCompartment() const
Definition: ReadKkit.cpp:110
std::string path(const std::string &separator="/") const
Definition: Id.cpp:76
void setupSlaveMsg(const string &src, const string &dest)
Definition: ReadKkit.cpp:1447
unsigned int value() const
Definition: Id.cpp:197
string pathTail(const string &path, string &head) const
Definition: ReadKkit.cpp:510
Definition: SetGet.h:236
Id id
Definition: ObjId.h:98
map< string, Id > chanIds_
Definition: ReadKkit.h:228
void separateVols(Id pool, double vol)
Definition: ReadKkit.cpp:700
double plotdt_
Timestep for updating control graphics.
Definition: ReadKkit.h:186
map< string, Id > poolIds_
Definition: ReadKkit.h:221
unsigned int loadTab(const vector< string > &args)
Definition: ReadKkit.cpp:1279
void innerRead(ifstream &fin)
Definition: ReadKkit.cpp:360
map< string, Id > tabIds_
Definition: ReadKkit.h:226
map< string, Id > reacIds_
Definition: ReadKkit.h:222
vector< vector< Id > > volCategories_
List of Ids in each unique volume.
Definition: ReadKkit.h:245
Id findSumTotSrc(const string &src)
Definition: ReadKkit.cpp:1078
virtual void zombieSwap(const Cinfo *zCinfo)
virtual func, this base version must be called by all derived classes
Definition: Element.cpp:159
unsigned int getVersion() const
Definition: ReadKkit.cpp:105
static Id child(const Eref &e, const string &name)
Definition: Neutral.cpp:665
void dumpPlots(const string &filename)
Definition: ReadKkit.cpp:347
int simpleWildcardFind(const string &path, vector< ObjId > &ret)
Definition: Wildcard.cpp:137
Definition: ObjId.h:20
void innerAddMsg(const string &src, const map< string, Id > &m1, const string &srcMsg, const string &dest, const map< string, Id > &m2, const string &destMsg, bool isBackward=0)
Definition: ReadKkit.cpp:1318
Eref eref() const
Definition: Id.cpp:125
bool useVariableDt_
Time to run model at fastdt.
Definition: ReadKkit.h:189
map< string, Id > enzIds_
Definition: ReadKkit.h:223
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:245
Id lastTab_
This keeps track of the last Table used in loadtab.
Definition: ReadKkit.h:240
ObjId doFind(const string &path) const
Definition: Shell.cpp:549
double getPlotDt() const
Definition: ReadKkit.cpp:90
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
map< string, int > groupMap_
Definition: ReadKkit.h:217
vector< pair< Id, Id > > enzCplxMols_
Definition: ReadKkit.h:247
unsigned int numCompartments_
Definition: ReadKkit.h:203
void convertParametersToConcUnits()
Definition: ReadKkit.cpp:1506
static SrcFinfo1< double > * output()
Definition: Arith.cpp:14
map< string, int > poolMap_
Definition: ReadKkit.h:214
void objdump(const vector< string > &args)
Definition: ReadKkit.cpp:568
void convertMMenzRatesToConcUnits()
Definition: ReadKkit.cpp:1562
map< Id, double > poolVols_
Definition: ReadKkit.h:251
string lower(const string &input)
Definition: ReadKkit.cpp:42
double getDefaultVol() const
Definition: ReadKkit.cpp:95
void addmsg(const vector< string > &args)
Definition: ReadKkit.cpp:1346
unsigned int numReacs_
Definition: ReadKkit.h:205
Id buildPlot(const vector< string > &args)
Definition: ReadKkit.cpp:1222
void setMethod(Shell *s, Id mgr, double simdt, double plotdt, const string &method)
Definition: ReadKkit.cpp:219
Shell * shell_
Definition: ReadKkit.h:253
Id buildReac(const vector< string > &args)
Definition: ReadKkit.cpp:668
static const Cinfo * initCinfo()
Definition: BufPool.cpp:18
void convertPoolAmountToConcUnits()
Convert pool amounts. Initially given in n, but scaling issue.
Definition: ReadKkit.cpp:1514
map< string, Id > stimIds_
Definition: ReadKkit.h:227
bool moveOntoCompartment_
Initdump too has a version.
Definition: ReadKkit.h:201
static const Cinfo * initCinfo()
Definition: ReacBase.cpp:33
void textload(const vector< string > &args)
Definition: ReadKkit.cpp:621
double simdt_
fast numerical timestep from kkit.
Definition: ReadKkit.h:184
vector< unsigned int > findVolOrder(const vector< double > &vols)
Definition: ReadKkit.cpp:723
unsigned int numMMenz_
Definition: ReadKkit.h:207
map< string, int > chanMap_
Definition: ReadKkit.h:220
ParseMode readInit(const string &line)
Definition: ReadKkit.cpp:439
Id buildEnz(const vector< string > &args)
Definition: ReadKkit.cpp:883
Id buildChan(const vector< string > &args)
Definition: ReadKkit.cpp:1182
vector< double > vols_
This keeps track of unique volumes.
Definition: ReadKkit.h:237
bool isA(const string &ancestor) const
Definition: Cinfo.cpp:280
map< string, int > reacMap_
Definition: ReadKkit.h:215
const Cinfo * cinfo() const
Definition: Element.cpp:66
Id buildText(const vector< string > &args)
Definition: ReadKkit.cpp:968
unsigned int chopLine(const string &line, vector< string > &ret)
Definition: ReadKkit.cpp:31
unsigned int lineNum_
Definition: ReadKkit.h:212
string getBasePath() const
Definition: ReadKkit.cpp:100
ReadKkit()
Definition: ReadKkit.cpp:52
Id buildInfo(Id parent, map< string, int > &m, const vector< string > &args)
Definition: ReadKkit.cpp:975
Id read(const string &filename, const string &cellname, Id parent, const string &solverClass="Stoich")
Definition: ReadKkit.cpp:276
Id buildCompartment(const vector< string > &args)
Definition: ReadKkit.cpp:661
void setMoveOntoCompartment(bool v)
Definition: ReadKkit.cpp:115
unsigned int numPools_
Definition: ReadKkit.h:204
Id makeStandardElements(Id pa, const string &modelname)
Definition: ReadKkit.cpp:123
void doReinit()
Definition: Shell.cpp:362
static char name[]
Definition: mfield.cpp:401
ObjId getCompt(Id id)
Id buildPool(const vector< string > &args)
Definition: ReadKkit.cpp:1015
unsigned int numOthers_
Definition: ReadKkit.h:210
unsigned int numStim_
Definition: ReadKkit.h:209
map< string, Id > plotIds_
Definition: ReadKkit.h:225
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
Id findParentComptOfReac(Id reac)
Definition: ReadKkit.cpp:789
void assignReacCompartments()
Definition: ReadKkit.cpp:810
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:153
void call(const vector< string > &args)
Definition: ReadKkit.cpp:585
unsigned int numEnz_
Definition: ReadKkit.h:206
Definition: Id.h:17
void run()
Definition: ReadKkit.cpp:321
Id buildGraph(const vector< string > &args)
Definition: ReadKkit.cpp:1209
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
Definition: Element.cpp:949
void doUseClock(string path, string field, unsigned int tick)
Definition: Shell.cpp:382
static A get(const ObjId &dest, const string &field)
Definition: SetGet.h:284
double controldt_
regular numerical timestep from kkit.
Definition: ReadKkit.h:185
static void positionCompt(ObjId compt, double side, bool shiftUp)
Definition: ReadKkit.cpp:153
std::string trim(const std::string myString, const string &delimiters)
Definition: strutil.cpp:53
void assignMMenzCompartments()
Definition: ReadKkit.cpp:868
string cleanPath(const string &path) const
Definition: ReadKkit.cpp:519
map< Id, int > poolFlags_
Definition: ReadKkit.h:249
map< string, Id > mmEnzIds_
Definition: ReadKkit.h:224
map< string, int > enzMap_
Definition: ReadKkit.h:216
unsigned int numPlot_
Definition: ReadKkit.h:208
void assignPoolCompartments()
Definition: ReadKkit.cpp:740
static char path[]
Definition: mfield.cpp:403
static const double KKIT_NA
Definition: ReadKkit.cpp:29
string basePath_
Definition: ReadKkit.h:180
static const Cinfo * initCinfo()
Definition: EnzBase.cpp:33
Definition: Shell.h:43
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
static const double EPSILON
Definition: ReadKkit.h:255
double lookupVolumeFromMesh(const Eref &e)
Definition: Finfo.h:12
void buildSumTotal(const string &src, const string &dest)
Definition: ReadKkit.cpp:1098
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2)
Definition: SetGet.h:365
void doMove(Id orig, ObjId newParent)
Definition: Shell.cpp:390