COPASI API  4.16.103
CModelAnalyzer.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CModelAnalyzer.cpp,v $
3 // $Revision: 1.11 $
4 // $Name: $
5 // $Author: shoops $
6 // $Date: 2011/03/07 19:30:51 $
7 // End CVS Header
8 
9 // Copyright (C) 2011 - 2010 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., University of Heidelberg, and The University
11 // of Manchester.
12 // All rights reserved.
13 
14 // Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
15 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
16 // and The University of Manchester.
17 // All rights reserved.
18 
19 // Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
20 // Properties, Inc. and EML Research, gGmbH.
21 // All rights reserved.
22 
23 #include "CModelAnalyzer.h"
24 
25 //#include "CEvaluationNode.h"
26 //#include "CEvaluationNodeOperator.h"
27 //#include "CFunction.h"
28 #include "CModel.h"
29 #include "report/CKeyFactory.h"
32 
34 {
35  checkModel(model);
36 }
37 
39 {
40  if (!model) return;
41 
42  mpModel = model;
43 
44  size_t i, imax = model->getTotSteps();
45 
46  for (i = 0; i < imax; ++i)
47  {
48  mReactionResults.push_back(checkReaction(model->getReactions()[i]));
49  }
50 }
51 
53 {
54  ReactionResult ret;
55 
56  if (!reaction) return ret;
57 
58  ret.mReactionName = reaction->getObjectName();
59 
60  //reversibility
61  if (reaction->getFunction()->isReversible() == TriUnspecified)
62  {
63  //warning
64  // Kinetics is of unspecified reversibility.
66  }
67  else if (((reaction->getFunction()->isReversible() == TriTrue) && !reaction->isReversible())
68  || ((reaction->getFunction()->isReversible() == TriFalse) && reaction->isReversible()))
69  {
70  //error; or COPASI error?
71  // Reversibility of function and kinetics does not match.
72  ret.mReversibilityMismatch = true;
73  }
74  else
75  {
76  //OK.
77  }
78 
79  if (dynamic_cast<const CMassAction*>(reaction->getFunction())) return ret;
80 
81  //TODO special case mass action
82 
83  //********* mapping **********************
84 
85  size_t i, imax;
86  imax = reaction->getChemEq().getSubstrates().size();
87 
88  for (i = 0; i < imax; ++i)
89  {
90  //each substrate of the reaction needs to be mapped to a function parameter with role SUBSTRATE
91  std::string tmpkey = reaction->getChemEq().getSubstrates()[i]->getMetaboliteKey();
92 
93  size_t j, jmax = reaction->getFunctionParameters().size();
94 
95  for (j = 0; j < jmax; ++j)
96  {
97  if ((reaction->getFunctionParameters()[j]->getUsage() == CFunctionParameter::SUBSTRATE)
98  && reaction->getParameterMappings()[j][0] == tmpkey)
99  break;
100  }
101 
102  if (j == jmax)
103  {
104  //warning/error?
105  // A substrate of this reaction is not mapped to a corresponding function parameter.
106  const CMetab * pM = reaction->getChemEq().getSubstrates()[i]->getMetabolite();
107 
108  if (pM)
109  ret.mChemEqSubs.push_back(pM->getObjectName());
110  }
111  }
112 
113  //for reversible reactions each product of the reaction needs to be mapped to a function parameter with role PRODUCT
114  if (reaction->getFunction()->isReversible() == TriTrue)
115  {
116  imax = reaction->getChemEq().getProducts().size();
117 
118  for (i = 0; i < imax; ++i)
119  {
120  std::string tmpkey = reaction->getChemEq().getProducts()[i]->getMetaboliteKey();
121 
122  size_t j, jmax = reaction->getFunctionParameters().size();
123 
124  for (j = 0; j < jmax; ++j)
125  {
126  if ((reaction->getFunctionParameters()[j]->getUsage() == CFunctionParameter::PRODUCT)
127  && reaction->getParameterMappings()[j][0] == tmpkey)
128  break;
129  }
130 
131  if (j == jmax)
132  {
133  //warning/error?
134  // A product of this reaction is not mapped to a corresponding function parameter.
135  const CMetab * pM = reaction->getChemEq().getProducts()[i]->getMetabolite();
136 
137  if (pM)
138  ret.mChemEqProds.push_back(pM->getObjectName());
139  }
140  }
141  }
142 
143  imax = reaction->getChemEq().getModifiers().size();
144 
145  for (i = 0; i < imax; ++i)
146  {
147  //each modifier of the reaction should be mapped to a function parameter with role MODIFIER
148  std::string tmpkey = reaction->getChemEq().getModifiers()[i]->getMetaboliteKey();
149 
150  size_t j, jmax = reaction->getFunctionParameters().size();
151 
152  for (j = 0; j < jmax; ++j)
153  {
154  if ((reaction->getFunctionParameters()[j]->getUsage() == CFunctionParameter::MODIFIER)
155  && reaction->getParameterMappings()[j][0] == tmpkey)
156  break;
157  }
158 
159  if (j == jmax)
160  {
161  //warning
162  // A modifier of this reaction is not mapped to a corresponding function parameter.
163  const CMetab * pM = reaction->getChemEq().getModifiers()[i]->getMetabolite();
164 
165  if (pM)
166  ret.mChemEqMods.push_back(pM->getObjectName());
167  }
168  }
169 
170  size_t j, jmax;
171 
172  //loop over all function parameters
173  imax = reaction->getFunctionParameters().size();
174 
175  for (i = 0; i < imax; ++i)
176  {
177  CFunctionParameter::Role role = reaction->getFunctionParameters()[i]->getUsage();
178 
179  // substr., product, modifier must be matched to a metab (COPASI bug!)
181  || role == CFunctionParameter::PRODUCT
182  || role == CFunctionParameter::MODIFIER)
183  {
184  if (!dynamic_cast<CMetab*>(CCopasiRootContainer::getKeyFactory()->get(reaction->getParameterMappings()[i][0])))
185  {
186  //COPASI bug!
187  // COPASI bug! Something that is not a metabolite is mapped to a (subs/prod/mod) function parameter.
188  ret.mNotMetabolite.push_back(reaction->getFunctionParameters()[i]->getObjectName());
189  }
190  }
191 
192  switch (role)
193  {
194  //substrate must be matched to a substr. of the reaction (COPASI bug?)
196  jmax = reaction->getChemEq().getSubstrates().size();
197 
198  for (j = 0; j < jmax; ++j)
199  {
200  if (reaction->getParameterMappings()[i][0]
201  == reaction->getChemEq().getSubstrates()[j]->getMetaboliteKey())
202  break;
203  }
204 
205  if (j == jmax)
206  {
207  //COPASI error?
208  // A SUBSTRATE function parameter is not mapped to a substrate of the reaction.
209  ret.mFunctionParametersSubs.push_back(reaction->getFunctionParameters()[i]->getObjectName());
210  }
211 
212  break;
213 
214  //Product must be matched to a product of the reaction (COPASI bug?)
216  jmax = reaction->getChemEq().getProducts().size();
217 
218  for (j = 0; j < jmax; ++j)
219  {
220  if (reaction->getParameterMappings()[i][0]
221  == reaction->getChemEq().getProducts()[j]->getMetaboliteKey())
222  break;
223  }
224 
225  if (j == jmax)
226  {
227  //COPASI error?
228  // A PRODUCT function parameter is not mapped to a product of the reaction." << std::endl;
229  ret.mFunctionParametersProds.push_back(reaction->getFunctionParameters()[i]->getObjectName());
230  }
231 
232  break;
233 
234  //modifier should be matched to a modifier in the chemeq
236  jmax = reaction->getChemEq().getModifiers().size();
237 
238  for (j = 0; j < jmax; ++j)
239  {
240  if (reaction->getParameterMappings()[i][0]
241  == reaction->getChemEq().getModifiers()[j]->getMetaboliteKey())
242  break;
243  }
244 
245  if (j == jmax)
246  {
247  //COPASI error?
248  // A MODIFIER function parameter is not mapped to a modifier of the reaction.
249  ret.mFunctionParametersMods.push_back(reaction->getFunctionParameters()[i]->getObjectName());
250  //this is not a user error. The modifier should have been added to the chemeq automatically.
251  }
252 
253  break;
254 
255  //parameter must be matched to a local or global parameter (COPASI bug)
257  //first search in local parameters list
258  jmax = reaction->getParameters().size();
259 
260  for (j = 0; j < jmax; ++j)
261  {
262  if (reaction->getParameterMappings()[i][0]
263  == reaction->getParameters().getParameter(j)->getKey())
264  break;
265  }
266 
267  if (j == jmax) //not a local parameter
268  {
269  //now search in global value list
270  jmax = mpModel->getModelValues().size();
271 
272  for (j = 0; j < jmax; ++j)
273  {
274  if (reaction->getParameterMappings()[i][0]
275  == mpModel->getModelValues()[j]->getKey())
276  break;
277  }
278 
279  if (j == jmax) //not a global parameter
280  {
281  //COPASI bug
282  // A PARAMETER function parameter is mapped neither to a local parameter nor a global value.
283  ret.mFunctionParametersParams.push_back(reaction->getFunctionParameters()[i]->getObjectName());
284  }
285  }
286 
287  break;
288 
290  jmax = mpModel->getCompartments().size();
291 
292  for (j = 0; j < jmax; ++j)
293  {
294  if (reaction->getParameterMappings()[i][0]
295  == mpModel->getCompartments()[j]->getKey())
296  break;
297  }
298 
299  if (j == jmax)
300  {
301  //COPASI bug
302  // A VOLUME function parameter is not mapped to a compartment.
303  ret.mFunctionParametersVol.push_back(reaction->getFunctionParameters()[i]->getObjectName());
304  }
305 
306  break;
307 
309 
310  if (reaction->getParameterMappings()[i][0] != mpModel->getKey())
311  {
312  //COPASI bug
313  // Internal Copasi bug: TIME parameter not mapped correctly.
314  ret.mFunctionParametersTime.push_back(reaction->getFunctionParameters()[i]->getObjectName());
315  }
316 
317  break;
318 
321  {
322  //COPASI bug
323  // Don't know what to do with a VARIABLE parameter here..."
324  ret.mFunctionParametersVar.push_back(reaction->getFunctionParameters()[i]->getObjectName());
325  }
326  break;
327  }
328  }
329 
330  //check function:
331  // irrev: no products should occur
332  // irrev: if substr=0 -> kinetics=0
333  CFunctionAnalyzer fa(reaction->getFunction() , reaction);
334  ret.mFunctionResult = fa.getResult();
335 
336  return ret;
337 }
338 
339 //*********** Reporting **********************************
340 
341 #define WRITE(__level, __text) os << CFunctionAnalyzer::write(__level, rt, __text, "");
342 
343 bool CModelAnalyzer::ReactionResult::writeResult(std::ostream & os, bool rt, bool verbose) const
344 {
345  bool ret = false;
346 
347  //reaction name
348  if (rt) os << "<h2>";
349 
350  os << mReactionName;
351 
352  if (rt) os << "</h2>";
353 
354  os << "\n";
355 
356  //reaction results
358  os << CFunctionAnalyzer::write(1, rt, "The kinetic function has unspecified reversibility.",
359  "This means that checking the kinetic function will be less strict.");
360 
362  os << CFunctionAnalyzer::write(3, rt, "The reversibility of the reaction and the kinetic function doesn't match.", "");
363 
364  size_t i, imax;
365  imax = mChemEqSubs.size();
366 
367  for (i = 0; i < imax; ++i)
368  {
369  os << CFunctionAnalyzer::write(2, rt, "The reaction substrate \""
370  + mChemEqSubs[i]
371  + "\" is not mapped to a corresponding function parameter.", "");
372  }
373 
374  imax = mChemEqProds.size();
375 
376  for (i = 0; i < imax; ++i)
377  {
378  os << CFunctionAnalyzer::write(2, rt, "The reaction product \""
379  + mChemEqProds[i]
380  + "\" is not mapped to a corresponding function parameter.", "");
381  }
382 
383  imax = mChemEqMods.size();
384 
385  for (i = 0; i < imax; ++i)
386  {
387  os << CFunctionAnalyzer::write(1, rt, "The reaction modifier \""
388  + mChemEqMods[i]
389  + "\" is not mapped to a corresponding function parameter.", "");
390  }
391 
392  imax = mNotMetabolite.size();
393 
394  for (i = 0; i < imax; ++i)
395  {
396  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
397  + mNotMetabolite[i]
398  + "\" which should be mapped to a metabolite is mapped to something else.", "");
399  }
400 
401  imax = mFunctionParametersSubs.size();
402 
403  for (i = 0; i < imax; ++i)
404  {
405  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
407  + "\" is not mapped to a substrate of the reaction.", "");
408  }
409 
410  imax = mFunctionParametersProds.size();
411 
412  for (i = 0; i < imax; ++i)
413  {
414  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
416  + "\" is not mapped to a product of the reaction.", "");
417  }
418 
419  imax = mFunctionParametersMods.size();
420 
421  for (i = 0; i < imax; ++i)
422  {
423  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
425  + "\" is not mapped to a modifier of the reaction.", "");
426  }
427 
428  imax = mFunctionParametersParams.size();
429 
430  for (i = 0; i < imax; ++i)
431  {
432  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
434  + "\" is not mapped to local parameter or a global value.", "");
435  }
436 
437  imax = mFunctionParametersVol.size();
438 
439  for (i = 0; i < imax; ++i)
440  {
441  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
443  + "\" is not mapped to a compartment.", "");
444  }
445 
446  imax = mFunctionParametersTime.size();
447 
448  for (i = 0; i < imax; ++i)
449  {
450  os << CFunctionAnalyzer::write(3, rt, "The function parameter \""
452  + "\" is not correctly handled as model time.", "");
453  }
454 
455  imax = mFunctionParametersVar.size();
456 
457  for (i = 0; i < imax; ++i)
458  {
459  os << CFunctionAnalyzer::write(1, rt, "The function parameter \""
461  + "\" is marked as \"variable\". Not sure what this means.", "");
462  }
463 
464  //function results
465  std::ostringstream tmpss;
466  bool eee = mFunctionResult.writeResult(tmpss, rt, verbose);
467 
468  if (eee) ret = true;
469 
470  if (eee || verbose)
471  {
472  os << tmpss.str();
473  }
474 
475  return ret;
476 }
477 
478 void CModelAnalyzer::writeReport(std::ostream & os, bool rt, bool verbose) const
479 {
480 
481  //reaction results
482  size_t i, imax = mReactionResults.size();
483 
484  for (i = 0; i < imax; ++i)
485  {
486  //std::ostringstream tmpss;
487  mReactionResults[i].writeResult(os, rt, verbose);
488  }
489 }
std::vector< std::string > mChemEqProds
CFunctionAnalyzer::Result mFunctionResult
const std::string & getObjectName() const
const CCopasiVectorN< CModelValue > & getModelValues() const
Definition: CModel.cpp:1060
virtual size_t size() const
const CModel * mpModel
std::vector< std::string > mFunctionParametersProds
std::vector< std::string > mFunctionParametersVol
Definition: CMetab.h:178
void checkModel(const CModel *model)
std::vector< std::string > mFunctionParametersSubs
bool writeResult(std::ostream &os, bool rt, bool verbose) const
size_t getTotSteps() const
Definition: CModel.cpp:1136
virtual const std::string & getKey() const
const CCopasiVector< CChemEqElement > & getProducts() const
Definition: CChemEq.cpp:63
const CFunction * getFunction() const
Definition: CReaction.cpp:252
const CFunctionParameters & getFunctionParameters() const
Definition: CReaction.cpp:576
const TriLogic & isReversible() const
Definition: CFunction.cpp:145
virtual const std::string & getKey() const
static std::string write(int level, bool rt, const std::string &text, const std::string &longText)
std::vector< std::string > mFunctionParametersMods
std::vector< std::string > mFunctionParametersTime
CCopasiParameter * getParameter(const std::string &name)
const CCopasiVector< CChemEqElement > & getSubstrates() const
Definition: CChemEq.cpp:60
const std::string & getKey() const
Definition: CModel.cpp:1142
bool isReversible() const
Definition: CReaction.cpp:229
CModelAnalyzer(const CModel *model)
CCopasiVectorNS< CCompartment > & getCompartments()
Definition: CModel.cpp:1145
std::vector< std::string > mChemEqSubs
std::vector< std::string > mFunctionParametersVar
static CKeyFactory * getKeyFactory()
const CCopasiVector< CChemEqElement > & getModifiers() const
Definition: CChemEq.cpp:66
const CCopasiParameterGroup & getParameters() const
Definition: CReaction.cpp:333
std::vector< std::string > mNotMetabolite
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
std::vector< ReactionResult > mReactionResults
Definition: CModel.h:50
const std::vector< std::vector< std::string > > & getParameterMappings() const
Definition: CReaction.h:285
ReactionResult checkReaction(const CReaction *reaction)
std::vector< std::string > mFunctionParametersParams
void writeReport(std::ostream &os, bool rt, bool verbose) const
const CChemEq & getChemEq() const
Definition: CReaction.cpp:223
bool writeResult(std::ostream &os, bool rt, bool verbose) const
std::vector< std::string > mChemEqMods