/** * Creates the data generators for SEDML. */ void CSEDMLExporter::createDataGenerators(CCopasiDataModel & dataModel, std::string & taskId, CCopasiTask* task) { const CModel* pModel = dataModel.getModel(); std::vector<std::string> stringsContainer; //split string container if (pModel == NULL) CCopasiMessage(CCopasiMessage::ERROR, "SED-ML: No model for this SED-ML document. An SBML model must exist for every SED-ML document."); SedPlot2D* pPSedPlot; SedCurve* pCurve; // = pPSedPlot->createCurve(); //create generator for special varibale time const CCopasiObject* pTime = static_cast<const CCopasiObject *>(dataModel.getModel()->getObject(CCopasiObjectName("Reference=Time"))); SedDataGenerator *pTimeDGenp = this->mpSEDMLDocument->createDataGenerator(); pTimeDGenp->setId("time"); pTimeDGenp->setName(pTime->getObjectName()); SedVariable *pTimeVar = pTimeDGenp->createVariable(); pTimeVar->setId("var_time"); pTimeVar->setTaskReference(taskId); pTimeVar->setSymbol(SEDML_TIME_URN); pTimeDGenp->setMath(SBML_parseFormula(pTimeVar->getId().c_str())); size_t i, imax = dataModel.getPlotDefinitionList()->size(); SedDataGenerator *pPDGen; if (imax == 0 && (task == NULL || task->getReport().getTarget().empty())) CCopasiMessage(CCopasiMessage::ERROR, "SED-ML: No plot/report definition for this SED-ML document."); // export report if (task != NULL && !task->getReport().getTarget().empty()) { CReportDefinition* def = task->getReport().getReportDefinition(); if (def != NULL) { SedReport* pReport = mpSEDMLDocument->createReport(); std::string name = def->getObjectName(); SEDMLUtils::removeCharactersFromString(name, "[]"); // pReport->setId(SEDMLUtils::getNextId("report", mpSEDMLDocument->getNumOutputs())); pReport->setName(name); std::vector<CRegisteredObjectName> header = *def->getHeaderAddr(); std::vector<CRegisteredObjectName> body = def->isTable() ? *def->getTableAddr() : *def->getBodyAddr(); int dsCount = 0; for (size_t i = 0; i < body.size(); ++i) { CRegisteredObjectName& current = body[i]; if (current == def->getSeparator().getCN()) continue; CCopasiObject *object = dataModel.getDataObject(current); if (object == NULL) continue; const std::string& typeX = object->getObjectName(); std::string xAxis = object->getObjectDisplayName(); std::string targetXPathStringX = SEDMLUtils::getXPathAndName(xAxis, typeX, pModel, dataModel); if (object->getCN() == pTime->getCN()) pPDGen = pTimeDGenp; else pPDGen = createDataGenerator( this->mpSEDMLDocument, xAxis, targetXPathStringX, taskId, i, 0 ); SedDataSet* pDS = pReport->createDataSet(); pDS->setId(SEDMLUtils::getNextId("ds", ++dsCount)); if (def->isTable()) { CCopasiObject *headerObj = NULL; if (header.size() > i) headerObj = dataModel.getDataObject(header[i]); else headerObj = dataModel.getDataObject(body[i]); if (headerObj != NULL) pDS->setLabel(headerObj->getObjectDisplayName()); else pDS->setLabel(xAxis); } else pDS->setLabel(xAxis); pDS->setDataReference(pPDGen->getId()); } } } // export plots for (i = 0; i < imax; i++) { pPSedPlot = this->mpSEDMLDocument->createPlot2D(); const CPlotSpecification* pPlot = (*dataModel.getPlotDefinitionList())[i]; std::string plotName = pPlot->getObjectName(); SEDMLUtils::removeCharactersFromString(plotName, "[]"); pPSedPlot->setId(SEDMLUtils::getNextId("plot", mpSEDMLDocument->getNumOutputs())); pPSedPlot->setName(plotName); size_t j, jmax = pPlot->getItems().size(); for (j = 0; j < jmax; j++) { const CPlotItem* pPlotItem = pPlot->getItems()[j]; CCopasiObject *objectX, *objectY; if (pPlotItem->getChannels().size() >= 1) { objectX = dataModel.getDataObject(pPlotItem->getChannels()[0]); } else { CCopasiMessage(CCopasiMessage::WARNING, "SED-ML: Can't export plotItem '%s', as it has no data channel.", pPlotItem->getObjectName().c_str()); continue; } if (objectX == NULL) { CCopasiMessage(CCopasiMessage::WARNING, "SED-ML: Can't export plotItem '%s' variable '%s', as it cannot be resolved.", pPlotItem->getObjectName().c_str(), pPlotItem->getChannels()[0].c_str()); continue; } bool xIsTime = objectX->getCN() == pTime->getCN(); if (pPlotItem->getChannels().size() >= 2) { objectY = dataModel.getDataObject(pPlotItem->getChannels()[1]); } else { CCopasiMessage(CCopasiMessage::WARNING, "SED-ML: Can't export plotItem '%s', as it has only 1 data channel.", pPlotItem->getObjectName().c_str()); continue; } if (objectY == NULL) { CCopasiMessage(CCopasiMessage::WARNING, "SED-ML: Can't export plotItem '%s' variable '%s', as it cannot be resolved.", pPlotItem->getObjectName().c_str(), pPlotItem->getChannels()[1].c_str()); continue; } const std::string& type = objectY->getObjectName(); std::string yAxis = objectY->getObjectDisplayName(); std::string sbmlId = yAxis; std::string targetXPathString = SEDMLUtils::getXPathAndName(sbmlId, type, pModel, dataModel); if (targetXPathString.empty()) { CCopasiMessage(CCopasiMessage::WARNING, "SED-ML: Can't export plotItem '%s' variable '%s', as no xpath expression for it could be generated.", pPlotItem->getObjectName().c_str(), pPlotItem->getChannels()[1].c_str()); continue; } pPDGen = createDataGenerator( this->mpSEDMLDocument, sbmlId, targetXPathString, taskId, i, j ); pPDGen->setName(yAxis); pCurve = pPSedPlot->createCurve(); std::ostringstream idCurveStrStream; idCurveStrStream << "p"; idCurveStrStream << i + 1; idCurveStrStream << "_curve_"; idCurveStrStream << j + 1; pCurve->setId(idCurveStrStream.str()); pCurve->setLogX(pPlot->isLogX()); pCurve->setLogY(pPlot->isLogY()); pCurve->setName(yAxis); pCurve->setYDataReference(pPDGen->getId()); if (xIsTime) { pCurve->setXDataReference(pTimeDGenp->getId()); } else { const std::string& typeX = objectX->getObjectName(); std::string xAxis = objectX->getObjectDisplayName(); std::string targetXPathStringX = SEDMLUtils::getXPathAndName(xAxis, typeX, pModel, dataModel); pPDGen = createDataGenerator( this->mpSEDMLDocument, xAxis, targetXPathStringX, taskId, i, j ); pCurve->setXDataReference(pPDGen->getId()); } } } }
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); }
int main(int argc, char** argv) { // initialize the backend library CCopasiRootContainer::init(argc, argv); assert(CCopasiRootContainer::getRoot() != NULL); // create a new datamodel CCopasiDataModel* pDataModel = CCopasiRootContainer::addDatamodel(); assert(CCopasiRootContainer::getDatamodelList()->size() == 1); // the only argument to the main routine should be the name of an SBML file if (argc == 2) { std::string filename = argv[1]; try { // load the model without progress report pDataModel->importSBML(filename, NULL); } catch (...) { std::cerr << "Error while importing the model from file named \"" << filename << "\"." << std::endl; CCopasiRootContainer::destroy(); return 1; } CModel* pModel = pDataModel->getModel(); assert(pModel != NULL); // create a report with the correct filename and all the species against // time. CReportDefinitionVector* pReports = pDataModel->getReportDefinitionList(); // create a new report definition object CReportDefinition* pReport = pReports->createReportDefinition("Report", "Output for timecourse"); // set the task type for the report definition to timecourse pReport->setTaskType(CTaskEnum::timeCourse); // we don't want a table pReport->setIsTable(false); // the entries in the output should be seperated by a ", " pReport->setSeparator(", "); // we need a handle to the header and the body // the header will display the ids of the metabolites and "time" for // the first column // the body will contain the actual timecourse data std::vector<CRegisteredObjectName>* pHeader = pReport->getHeaderAddr(); std::vector<CRegisteredObjectName>* pBody = pReport->getBodyAddr(); pBody->push_back(CCopasiObjectName(pDataModel->getModel()->getCN() + ",Reference=Time")); pBody->push_back(CRegisteredObjectName(pReport->getSeparator().getCN())); pHeader->push_back(CCopasiStaticString("time").getCN()); pHeader->push_back(pReport->getSeparator().getCN()); size_t i, iMax = pModel->getMetabolites().size(); for (i = 0; i < iMax; ++i) { CMetab* pMetab = &pModel->getMetabolites()[i]; assert(pMetab != NULL); // we don't want output for FIXED metabolites right now if (pMetab->getStatus() != CModelEntity::FIXED) { // we want the concentration oin the output // alternatively, we could use "Reference=Amount" to get the // particle number pBody->push_back(pMetab->getObject(CCopasiObjectName("Reference=Concentration"))->getCN()); // after each entry, we need a seperator pBody->push_back(pReport->getSeparator().getCN()); // add the corresponding id to the header pHeader->push_back(CCopasiStaticString(pMetab->getSBMLId()).getCN()); // and a seperator pHeader->push_back(pReport->getSeparator().getCN()); } } if (iMax > 0) { // delete the last separator // since we don't need one after the last element on each line if ((*pBody->rbegin()) == pReport->getSeparator().getCN()) { pBody->erase(--pBody->end()); } if ((*pHeader->rbegin()) == pReport->getSeparator().getCN()) { pHeader->erase(--pHeader->end()); } } // get the task list CCopasiVectorN< CCopasiTask > & TaskList = * pDataModel->getTaskList(); // get the trajectory task object CTrajectoryTask* pTrajectoryTask = dynamic_cast<CTrajectoryTask*>(&TaskList["Time-Course"]); // if there isn't one if (pTrajectoryTask == NULL) { // remove any existing trajectory task just to be sure since in // theory only the cast might have failed above TaskList.remove("Time-Course"); // create a new one pTrajectoryTask = new CTrajectoryTask(& TaskList); // add the new time course task to the task list TaskList.add(pTrajectoryTask, true); } // run a deterministic time course pTrajectoryTask->setMethodType(CTaskEnum::deterministic); // Activate the task so that it will be run when the model is saved // and passed to CopasiSE pTrajectoryTask->setScheduled(true); // set the report for the task pTrajectoryTask->getReport().setReportDefinition(pReport); // set the output filename pTrajectoryTask->getReport().setTarget("example3.txt"); // don't append output if the file exists, but overwrite the file pTrajectoryTask->getReport().setAppend(false); // get the problem for the task to set some parameters CTrajectoryProblem* pProblem = dynamic_cast<CTrajectoryProblem*>(pTrajectoryTask->getProblem()); // simulate 100 steps pProblem->setStepNumber(100); // start at time 0 pDataModel->getModel()->setInitialTime(0.0); // simulate a duration of 10 time units pProblem->setDuration(10); // tell the problem to actually generate time series data pProblem->setTimeSeriesRequested(true); // set some parameters for the LSODA method through the method CTrajectoryMethod* pMethod = dynamic_cast<CTrajectoryMethod*>(pTrajectoryTask->getMethod()); CCopasiParameter* pParameter = pMethod->getParameter("Absolute Tolerance"); assert(pParameter != NULL); pParameter->setValue(1.0e-12); try { // initialize the trajectory task // we want complete output (HEADER, BODY and FOOTER) // // The output has to be set to OUTPUT_UI, otherwise the time series will not be // kept in memory and some of the assert further down will fail // If it is OK that the output is only written to file, the output type can // be set to OUTPUT_SE pTrajectoryTask->initialize(CCopasiTask::OUTPUT_UI, pDataModel, NULL); // now we run the actual trajectory pTrajectoryTask->process(true); } catch (...) { std::cerr << "Error. Running the time course simulation failed." << std::endl; // check if there are additional error messages if (CCopasiMessage::size() > 0) { // print the messages in chronological order std::cerr << CCopasiMessage::getAllMessageText(true); } CCopasiRootContainer::destroy(); return 1; } // restore the state of the trajectory pTrajectoryTask->restore(); // look at the timeseries const CTimeSeries* pTimeSeries = &pTrajectoryTask->getTimeSeries(); // we simulated 100 steps, including the initial state, this should be // 101 step in the timeseries assert(pTimeSeries->getRecordedSteps() == 101); std::cout << "The time series consists of " << pTimeSeries->getRecordedSteps() << "." << std::endl; std::cout << "Each step contains " << pTimeSeries->getNumVariables() << " variables." << std::endl; std::cout << "The final state is: " << std::endl; iMax = pTimeSeries->getNumVariables(); size_t lastIndex = pTimeSeries->getRecordedSteps() - 1; for (i = 0; i < iMax; ++i) { // here we get the particle number (at least for the species) // the unit of the other variables may not be particle numbers // the concentration data can be acquired with getConcentrationData std::cout << pTimeSeries->getTitle(i) << ": " << pTimeSeries->getData(lastIndex, i) << std::endl; } } else { std::cerr << "Usage: example3 SBMLFILE" << std::endl; CCopasiRootContainer::destroy(); return 1; } // clean up the library CCopasiRootContainer::destroy(); }