Esempio n. 1
0
void test000087::test_simulate_reaction_flux_reference_1()
{
  try
    {
      bool result = pCOPASIDATAMODEL->importSBMLFromString(test000087::MODEL_STRING5);
      CPPUNIT_ASSERT(result = true);
    }
  catch (...)
    {
      // there should be no exception
      CPPUNIT_ASSERT(false);
    }

  CModel* pModel = pCOPASIDATAMODEL->getModel();
  CPPUNIT_ASSERT(pModel != NULL);
  CPPUNIT_ASSERT(pModel->getCompartments().size() == 1);
  CPPUNIT_ASSERT(pModel->getMetabolites().size() == 2);
  CPPUNIT_ASSERT(pModel->getModelValues().size() == 2);
  CPPUNIT_ASSERT(pModel->getReactions().size() == 1);
  const CReaction* pReaction = pModel->getReactions()[0];
  CPPUNIT_ASSERT(pReaction != NULL);
  CModelValue* pConstParameter = NULL;
  CModelValue* pNonConstParameter = NULL;
  unsigned int i, iMax = pModel->getModelValues().size();

  for (i = 0; i < iMax; ++i)
    {
      if (pModel->getModelValues()[i]->getStatus() == CModelEntity::FIXED)
        {
          pConstParameter = pModel->getModelValues()[i];
        }

      if (pModel->getModelValues()[i]->getStatus() == CModelEntity::ASSIGNMENT)
        {
          pNonConstParameter = pModel->getModelValues()[i];
        }
    }

  CPPUNIT_ASSERT(pConstParameter != NULL);
  CPPUNIT_ASSERT(pNonConstParameter != NULL);
  // check if the kinetic law is mass action with const global parameter as the kinetic constant
  CPPUNIT_ASSERT(pReaction->getChemEq().getSubstrates().size() == 1);
  CPPUNIT_ASSERT(pReaction->getChemEq().getProducts().size() == 1);
  CPPUNIT_ASSERT(pReaction->getChemEq().getModifiers().size() == 0);
  CPPUNIT_ASSERT(pReaction->isReversible() == false);
  const CFunction* pKineticLaw = pReaction->getFunction();
  CPPUNIT_ASSERT(pKineticLaw != NULL);
  CPPUNIT_ASSERT(pKineticLaw->getType() == CEvaluationTree::MassAction);
  const std::vector< std::vector<std::string> > & parameterMappings = pReaction->getParameterMappings();
  CPPUNIT_ASSERT(parameterMappings.size() == 2);
  CPPUNIT_ASSERT(parameterMappings[0].size() == 1);
  CPPUNIT_ASSERT(parameterMappings[0][0] == pConstParameter->getKey());
  CPPUNIT_ASSERT(parameterMappings[1].size() == 1);
  std::string substrateKey = parameterMappings[1][0];
  const CCopasiObject* pTempObject = CCopasiRootContainer::getKeyFactory()->get(substrateKey);
  CPPUNIT_ASSERT(pTempObject != NULL);
  const CMetab* pSubstrate = dynamic_cast<const CMetab*>(pTempObject);
  CPPUNIT_ASSERT(pSubstrate != NULL);
  // check that the assignment consists of only one object node that is a reference to the reaction flux
  const CExpression* pExpression = pNonConstParameter->getExpressionPtr();
  CPPUNIT_ASSERT(pExpression != NULL);
  const CEvaluationNode* pRoot = pExpression->getRoot();
  CPPUNIT_ASSERT(pRoot != NULL);
  CPPUNIT_ASSERT(CEvaluationNode::type(pRoot->getType()) == CEvaluationNode::OBJECT);
  const CEvaluationNodeObject* pObjectNode = dynamic_cast<const CEvaluationNodeObject*>(pRoot);
  CPPUNIT_ASSERT(pObjectNode != NULL);
  const CRegisteredObjectName cn = pObjectNode->getObjectCN();
  std::vector<CCopasiContainer*> listOfContainers;
  listOfContainers.push_back(pCOPASIDATAMODEL->getModel());
  const CCopasiObject* pObject = pCOPASIDATAMODEL->ObjectFromName(listOfContainers, cn);
  CPPUNIT_ASSERT(pObject != NULL);
  CPPUNIT_ASSERT(pObject->isReference() == true);
  CPPUNIT_ASSERT(pObject->getObjectName() == "Flux");
  CPPUNIT_ASSERT(pObject->getObjectParent() == pReaction);
  // Simulate the model (5 steps, stepsize 1 and check that at each step, the value of the variable parameter
  // is the same as the flux through the reaction.
  std::ostringstream result;
  // create a report with the correct filename and all the species against
  // time.
  CReportDefinitionVector* pReports = pCOPASIDATAMODEL->getReportDefinitionList();
  CReportDefinition* pReport = pReports->createReportDefinition("Report", "Output for simulation");
  pReport->setTaskType(CCopasiTask::timeCourse);
  pReport->setIsTable(false);
  pReport->setSeparator(CCopasiReportSeparator(", "));

  std::vector<CRegisteredObjectName>* pHeader = pReport->getHeaderAddr();
  std::vector<CRegisteredObjectName>* pBody = pReport->getBodyAddr();
  pHeader->push_back(CCopasiStaticString("time").getCN());
  pHeader->push_back(pReport->getSeparator().getCN());
  pHeader->push_back(CCopasiStaticString("substrate").getCN());
  pHeader->push_back(pReport->getSeparator().getCN());
  pHeader->push_back(CCopasiStaticString("reaction flux").getCN());
  pHeader->push_back(pReport->getSeparator().getCN());
  pHeader->push_back(CCopasiStaticString("variable model value").getCN());
  pBody->push_back(CCopasiObjectName(pCOPASIDATAMODEL->getModel()->getCN() + ",Reference=Time"));
  pBody->push_back(CRegisteredObjectName(pReport->getSeparator().getCN()));
  pBody->push_back(CCopasiObjectName(pSubstrate->getCN() + ",Reference=Concentration"));
  pBody->push_back(CRegisteredObjectName(pReport->getSeparator().getCN()));
  pBody->push_back(CCopasiObjectName(pReaction->getCN() + ",Reference=Flux"));
  pBody->push_back(CRegisteredObjectName(pReport->getSeparator().getCN()));
  pBody->push_back(CCopasiObjectName(pNonConstParameter->getCN() + ",Reference=Value"));
  //
  // create a trajectory task
  CTrajectoryTask* pTrajectoryTask = new CTrajectoryTask();
  // use LSODAR from now on since we will have events pretty soon
  pTrajectoryTask->setMethodType(CCopasiMethod::LSODAR);
  pTrajectoryTask->getProblem()->setModel(pCOPASIDATAMODEL->getModel());

  pTrajectoryTask->setScheduled(true);
  pTrajectoryTask->getReport().setReportDefinition(pReport);
  // the target needs to be set in order to get output on the stream
  // object passed to the task in the call to initialize below
  pTrajectoryTask->getReport().setTarget("test.tmp");

  CTrajectoryProblem* pProblem = dynamic_cast<CTrajectoryProblem*>(pTrajectoryTask->getProblem());

  pProblem->setStepNumber((const unsigned C_INT32)30);
  pCOPASIDATAMODEL->getModel()->setInitialTime((const C_FLOAT64)0.0);
  pProblem->setDuration((const C_FLOAT64)30);
  pProblem->setTimeSeriesRequested(true);

  CTrajectoryMethod* pMethod = dynamic_cast<CTrajectoryMethod*>(pTrajectoryTask->getMethod());

  pMethod->getParameter("Absolute Tolerance")->setValue(1.0e-12);

  CCopasiVectorN< CCopasiTask > & TaskList = * pCOPASIDATAMODEL->getTaskList();

  TaskList.remove("Time-Course");
  TaskList.add(pTrajectoryTask, true);

  try
    {
      pTrajectoryTask->initialize(CCopasiTask::OUTPUT_UI, pCOPASIDATAMODEL, &result);
      pTrajectoryTask->process(true);
      pTrajectoryTask->restore();
    }
  catch (...)
    {
      // there should be no exception
      CPPUNIT_ASSERT(false);
    }

  // analyse the result
  CPPUNIT_ASSERT(!result.str().empty());
  std::string result_string = result.str();
  std::string delimiter = "\n";
  std::string delimiter2 = ",";
  std::size_t lastPos = result_string.find_first_not_of(delimiter);
  std::size_t pos;
  std::string line, number_string;
  unsigned int index = 0;
  unsigned int index2;
  std::size_t lastPos2;
  std::size_t pos2;
  double last = std::numeric_limits<double>::max(), current = std::numeric_limits<double>::max();

  while (lastPos != std::string::npos)
    {
      pos = result_string.find_first_of(delimiter, lastPos);
      line = result_string.substr(lastPos, pos - lastPos);
      lastPos = result_string.find_first_not_of(delimiter, pos);
      lastPos2 = line.find_first_not_of(delimiter2);

      // skip the header line
      if (index != 0)
        {
          index2 = 0;

          while (lastPos2 != std::string::npos)
            {
              pos2 = line.find_first_of(delimiter2, lastPos2);
              number_string = line.substr(lastPos2, pos2 - lastPos2);
              lastPos2 = line.find_first_not_of(delimiter2, pos2);

              // skip the time column
              if (index2 != 0)
                {
                  //check that all values in the row (besides the time)
                  // are always the same
                  if (index2 == 1)
                    {
                      last = strToDouble(number_string.c_str(), NULL);

                      if (index == 1)
                        {
                          // just make sure that we don't compare all zeros
                          // The initial value of the substrate hould be higher than 1
                          CPPUNIT_ASSERT(fabs(pSubstrate->getInitialValue()) > 1);
                          // the first rwo should correspond the the initial value of the substrate
                          // We check this to make sure that the whole timeseries does not consist of zeros
                          CPPUNIT_ASSERT(fabs((last - pSubstrate->getInitialConcentration()) / pSubstrate->getInitialConcentration()) < 1e-20);
                        }
                    }
                  else
                    {
                      current = strToDouble(number_string.c_str(), NULL);
                      CPPUNIT_ASSERT(fabs((current - last) / last) < 1e-20);
                      last = current;
                    }
                }

              ++index2;
            }
        }

      ++index;
    }

  // make sure there actually were datapoints
  CPPUNIT_ASSERT(index > 1);
  // the simulation is set to run until all substrate is depleted, so in the end
  // last should be below the absolute tolerance for the simulation
  CPPUNIT_ASSERT(last < *pMethod->getParameter("Absolute Tolerance")->getValue().pDOUBLE);
}
void CFixLocalReactionParameters::changeModel()
{
  CCopasiParameter * pParameter = NULL;
  CModelValue * pModelValue = NULL;
  CReaction * pReaction = NULL;

  std::stringstream NameStream;
  std::stringstream Message;

  std::string OldCN;
  std::string NewCNBase;
  std::string NewCN;
  std::string Infix;

  std::string::size_type Start;

  // Loop through all changes.
  std::multimap< CCopasiParameter *, const CExpression * >::const_iterator itChanges = mChanges.begin();
  std::multimap< CCopasiParameter *, const CExpression * >::const_iterator endChanges = mChanges.end();

  for (; itChanges != endChanges; ++itChanges)
    {
      if (pParameter != itChanges->first)
        {
          // We have a new parameter
          pParameter = itChanges->first;
          OldCN = "<" + pParameter->getCN() + ",Reference=";

          // Create a global quantity of type FIXED.
          std::string Name = pParameter->getObjectName();
          pReaction = static_cast< CReaction * >(pParameter->getObjectAncestor("Reaction"));
          Name += "{" + pReaction->getObjectName() + "}";

          pModelValue = mpModel->createModelValue(Name, pParameter->getValue< C_FLOAT64 >());

          // In case the created name is not unique we append _n with increasing n
          // until we succeed;
          C_INT32 index = 0;

          while (pModelValue == NULL)
            {
              NameStream.str("");
              NameStream << Name << "_" << index++;
              pModelValue = mpModel->createModelValue(NameStream.str(), pParameter->getValue< C_FLOAT64 >());
            }

          NewCNBase = "<" + pModelValue->getCN() + ",Reference=";

          // If the parameter is actually used in the reaction
          // it is changed to the global quantity.
          if (pReaction->isLocalParameter(pParameter->getObjectName()))
            pReaction->setParameterMapping(pParameter->getObjectName(), pModelValue->getKey());

          Message << "  " << pParameter->getObjectName() << " in " << pReaction->getObjectName()
                  << " is replaced by " << pModelValue->getObjectName() << std::endl;
        }

      // We need to distinguish between initial and other expressions.
      if (itChanges->second->getObjectName().compare(0, 7, "Initial") == 0)
        NewCN = NewCNBase + "Initial";
      else
        NewCN = NewCNBase;

      // Replace the OldCN of the parameter with the NewCN of global quantity in all expressions.
      Infix = itChanges->second->getInfix();

      // There may be more than one occurrence.
      Start = 0;

      while ((Start = Infix.find(OldCN), Start) != std::string::npos)
        Infix.replace(Start, OldCN.length(), NewCN);

      const_cast< CExpression * >(itChanges->second)->setInfix(Infix);
    }

  CCopasiMessage(CCopasiMessage::WARNING, MCXML + 14, Message.str().c_str());
}