int main() { // initialize the backend library // since we are not interested in the arguments // that are passed to main, we pass 0 and NULL to // init CCopasiRootContainer::init(0, NULL); assert(CCopasiRootContainer::getRoot() != NULL); // create a new datamodel CCopasiDataModel* pDataModel = CCopasiRootContainer::addDatamodel(); assert(CCopasiRootContainer::getDatamodelList()->size() == 1); // get the model from the datamodel CModel* pModel = pDataModel->getModel(); assert(pModel != NULL); // set the units for the model // we want seconds as the time unit // microliter as the volume units // and nanomole as the substance units pModel->setTimeUnit(CModel::s); pModel->setVolumeUnit(CModel::microl); pModel->setQuantityUnit(CModel::nMol); // we have to keep a set of all the initial values that are changed during // the model building process // They are needed after the model has been built to make sure all initial // values are set to the correct initial value std::set<const CCopasiObject*> changedObjects; // create a compartment with the name cell and an initial volume of 5.0 // microliter CCompartment* pCompartment = pModel->createCompartment("cell", 5.0); const CCopasiObject* pObject = pCompartment->getValueReference(); assert(pObject != NULL); changedObjects.insert(pObject); assert(pCompartment != NULL); assert(pModel->getCompartments().size() == 1); // create a new metabolite with the name S and an inital // concentration of 10 nanomol // the metabolite belongs to the compartment we created and is is to be // fixed CMetab* pS = pModel->createMetabolite("S", pCompartment->getObjectName(), 10.0, CMetab::FIXED); pObject = pS->getInitialConcentrationReference(); assert(pObject != NULL); changedObjects.insert(pObject); assert(pCompartment != NULL); assert(pS != NULL); assert(pModel->getMetabolites().size() == 1); // create a second metabolite called P with an initial // concentration of 0. This metabolite is to be changed by reactions CMetab* pP = pModel->createMetabolite("P", pCompartment->getObjectName(), 0.0, CMetab::REACTIONS); assert(pP != NULL); pObject = pP->getInitialConcentrationReference(); assert(pObject != NULL); changedObjects.insert(pObject); assert(pModel->getMetabolites().size() == 2); // now we create a reaction CReaction* pReaction = pModel->createReaction("reaction"); assert(pReaction != NULL); assert(pModel->getReactions().size() == 1); // reaction converts S to P // we can set these on the chemical equation of the reaction CChemEq* pChemEq = &pReaction->getChemEq(); // S is a substrate with stoichiometry 1 pChemEq->addMetabolite(pS->getKey(), 1.0, CChemEq::SUBSTRATE); // P is a product with stoichiometry 1 pChemEq->addMetabolite(pP->getKey(), 1.0, CChemEq::PRODUCT); assert(pChemEq->getSubstrates().size() == 1); assert(pChemEq->getProducts().size() == 1); // this reaction is to be irreversible pReaction->setReversible(false); assert(pReaction->isReversible() == false); CModelValue* pMV = pModel->createModelValue("K", 42.0); // set the status to FIXED pMV->setStatus(CModelValue::FIXED); assert(pMV != NULL); pObject = pMV->getInitialValueReference(); assert(pObject != NULL); changedObjects.insert(pObject); assert(pModel->getModelValues().size() == 1); // now we ned to set a kinetic law on the reaction // for this we create a user defined function CFunctionDB* pFunDB = CCopasiRootContainer::getFunctionList(); assert(pFunDB != NULL); CKinFunction* pFunction = new CKinFunction("My Rate Law"); pFunDB->add(pFunction, true); CFunction* pRateLaw = dynamic_cast<CFunction*>(pFunDB->findFunction("My Rate Law")); assert(pRateLaw != NULL); // now we create the formula for the function and set it on the function std::string formula = "(1-0.4/(EXPONENTIALE^(temp-37)))*0.00001448471257*1.4^(temp-37)*substrate"; bool result = pFunction->setInfix(formula); assert(result == true); // make the function irreversible pFunction->setReversible(TriFalse); // the formula string should have been parsed now // and COPASI should have determined that the formula string contained 2 parameters (temp and substrate) CFunctionParameters& variables = pFunction->getVariables(); // per default the usage of those parameters will be set to VARIABLE size_t index = pFunction->getVariableIndex("temp"); assert(index != C_INVALID_INDEX); CFunctionParameter* pParam = variables[index]; assert(pParam->getUsage() == CFunctionParameter::VARIABLE); // This is correct for temp, but substrate should get the usage SUBSTRATE in order // for us to use the function with the reaction created above // So we need to set the usage for "substrate" manually index = pFunction->getVariableIndex("substrate"); assert(index != C_INVALID_INDEX); pParam = variables[index]; pParam->setUsage(CFunctionParameter::SUBSTRATE); // set the rate law for the reaction pReaction->setFunction(pFunction); assert(pReaction->getFunction() != NULL); // COPASI also needs to know what object it has to assocuiate with the individual function parameters // In our case we need to tell COPASI that substrate is to be replaced by the substrate of the reaction // and temp is to be replaced by the global parameter K pReaction->setParameterMapping("substrate", pS->getKey()); pReaction->setParameterMapping("temp", pMV->getKey()); // finally compile the model // compile needs to be done before updating all initial values for // the model with the refresh sequence pModel->compileIfNecessary(NULL); // now that we are done building the model, we have to make sure all // initial values are updated according to their dependencies std::vector<Refresh*> refreshes = pModel->buildInitialRefreshSequence(changedObjects); std::vector<Refresh*>::iterator it2 = refreshes.begin(), endit2 = refreshes.end(); while (it2 != endit2) { // call each refresh (**it2)(); ++it2; } // save the model to a COPASI file // we save to a file named example1.cps, we don't want a progress report // and we want to overwrite any existing file with the same name // Default tasks are automatically generated and will always appear in cps // file unless they are explicitley deleted before saving. pDataModel->saveModel("example7.cps", NULL, true); // export the model to an SBML file // we save to a file named example1.xml, we want to overwrite any // existing file with the same name and we want SBML L2V3 pDataModel->exportSBML("example7.xml", true, 2, 3); // destroy the root container once we are done CCopasiRootContainer::destroy(); }
/*static*/ void CChemEqInterface::setChemEqFromString(CModel * model, CReaction & rea, const std::string & ces) { CChemEqInterface cei(model); cei.setChemEqString(ces); cei.writeToChemEq(rea.getChemEq()); }
bool CModelMerging::mergeMetabolites(std::string toKey, std::string key) { bool info = false; //merge in the relevant reactions size_t i, imax = mpModel->getReactions().size(); size_t j, jmax; for (i = 0; i < imax; ++i) { CReaction * reac = &mpModel->getReactions()[i]; jmax = reac->getChemEq().getSubstrates().size(); for (j = 0; j < jmax; ++j) { CChemEqElement * subst = const_cast< CChemEqElement * >(&reac->getChemEq().getSubstrates()[j]); if (subst->getMetabolite()->getKey() == key) subst->setMetabolite(toKey); } jmax = reac->getChemEq().getProducts().size(); for (j = 0; j < jmax; ++j) { CChemEqElement * prod = const_cast< CChemEqElement * >(&reac->getChemEq().getProducts()[j]); if (prod->getMetabolite()->getKey() == key) prod->setMetabolite(toKey); } jmax = reac->getChemEq().getModifiers().size(); for (j = 0; j < jmax; ++j) { CChemEqElement * modif = const_cast< CChemEqElement * >(&reac->getChemEq().getModifiers()[j]); if (modif->getMetabolite()->getKey() == key) modif->setMetabolite(toKey); } //change parameters of the kinetic function for (j = 0; j < reac->getFunctionParameters().size(); ++j) { switch (reac->getFunctionParameters()[j]->getUsage()) { case CFunctionParameter::SUBSTRATE: case CFunctionParameter::PRODUCT: case CFunctionParameter::MODIFIER: //translate the metab keys { //we assume that only SUBSTRATE, PRODUCT, MODIFIER can be vectors size_t k, kmax = reac->getParameterMappings()[j].size(); for (k = 0; k < kmax; ++k) if (reac->getParameterMappings()[j][k] == key) reac->getParameterMappings()[j][k] = toKey; } break; case CFunctionParameter::TIME: break; case CFunctionParameter::VOLUME: // ??? TODO : have to ask break; case CFunctionParameter::PARAMETER: break; default: return info; break; } } } imax = mpModel->getEvents().size(); for (i = 0; i < imax; ++i) { CEvent * event = &mpModel->getEvents()[i]; if (!event) return info; /* merge in trigger expressions */ CExpression* pExpression = event->getTriggerExpressionPtr(); if (pExpression == NULL) return info; if (!mergeInExpression(toKey, key, pExpression)) return info; pExpression = event->getDelayExpressionPtr(); if (pExpression) if (!mergeInExpression(toKey, key, pExpression)) return info; jmax = event->getAssignments().size(); for (j = 0; j < jmax; ++j) { CEventAssignment* assignment = &event->getAssignments()[j]; if (!assignment) return info; std::string assignmentKey = assignment->getTargetKey(); if (assignmentKey == key) assignment->setTargetKey(toKey); pExpression = assignment->getExpressionPtr(); if (pExpression == NULL) return info; if (!mergeInExpression(toKey, key, pExpression)) return info; } } imax = mpModel->getMetabolites().size(); for (i = 0; i < imax; ++i) { CMetab* metab = &mpModel->getMetabolites()[i]; if (!metab) return info; switch (metab->getStatus()) { case CModelEntity::FIXED: case CModelEntity::REACTIONS: break; case CModelEntity::ASSIGNMENT: if (!mergeInExpression(toKey, key, metab->getExpressionPtr())) return info; break; case CModelEntity::ODE: if (!mergeInExpression(toKey, key, metab->getExpressionPtr())) return info; if (metab->getInitialExpression() != "") if (!mergeInExpression(toKey, key, metab->getInitialExpressionPtr())) return info; break; default: return info; break; } } imax = mpModel->getCompartments().size(); for (i = 0; i < imax; ++i) { CCompartment* comp = &mpModel->getCompartments()[i]; if (!comp) return info; switch (comp ->getStatus()) { case CModelEntity::FIXED: break; case CModelEntity::ASSIGNMENT: if (!mergeInExpression(toKey, key, comp->getExpressionPtr())) return info; break; case CModelEntity::ODE: if (!mergeInExpression(toKey, key, comp->getExpressionPtr())) return info; if (comp->getInitialExpression() != "") if (!mergeInExpression(toKey, key, comp->getInitialExpressionPtr())) return info; break; default: return info; break; } } imax = mpModel->getModelValues().size(); for (i = 0; i < imax; ++i) { CModelValue* modval = &mpModel->getModelValues()[i]; if (!modval) return info; switch (modval ->getStatus()) { case CModelEntity::FIXED: break; case CModelEntity::ASSIGNMENT: if (!mergeInExpression(toKey, key, modval->getExpressionPtr())) return info; break; case CModelEntity::ODE: if (!mergeInExpression(toKey, key, modval->getExpressionPtr())) return info; if (modval->getInitialExpression() != "") if (!mergeInExpression(toKey, key, modval->getInitialExpressionPtr())) return info; break; default: return info; break; } } return true; }
/*static*/ std::string CChemEqInterface::getChemEqString(CModel * model, const CReaction & rea, bool expanded) { CChemEqInterface cei(model); cei.loadFromChemEq(rea.getChemEq()); return cei.getChemEqString(expanded); }
bool CModelAdd::addReactions(std::string name) { bool info = false; //create copies of the relevant reactions size_t i, imax = mmModel->getReactions().size(); size_t ic, icmax = mmModel->getCompartments().size(); for (ic = 0; ic < icmax; ++ic) { const CCompartment* sourceComp = &mmModel->getCompartments()[ic]; if (!sourceComp) return info; for (i = 0; i < imax; ++i) { CReaction * sourceReac = &mmModel->getReactions()[i]; if (reactionInvolvesCompartment(sourceReac, sourceComp)) { std::string newName = sourceReac->getObjectName() + "_" + name; CReaction* newReac = mpModel->createReaction(newName); if (!newReac) return info; //copy the chemical equation. If the involved metabs are among those that //were copied with the compartment, replace them. Otherwise keep the original metab newReac->setReversible(sourceReac->isReversible()); std::map<std::string, std::string>::const_iterator mapIt; std::string targetKey; size_t j, jmax = sourceReac->getChemEq().getSubstrates().size(); for (j = 0; j < jmax; ++j) { const CChemEqElement * sourceElement = &sourceReac->getChemEq().getSubstrates()[j]; //check if the metab is in the map. If yes, translate it, otherwise not. mapIt = keyMap.find(sourceElement->getMetaboliteKey()); if (mapIt == keyMap.end()) { targetKey = sourceElement->getMetaboliteKey(); } else targetKey = mapIt->second; newReac->addSubstrate(targetKey, sourceElement->getMultiplicity()); } jmax = sourceReac->getChemEq().getProducts().size(); for (j = 0; j < jmax; ++j) { const CChemEqElement * sourceElement = &sourceReac->getChemEq().getProducts()[j]; //check if the metab is in the map. If yes, translate it, otherwise not. mapIt = keyMap.find(sourceElement->getMetaboliteKey()); if (mapIt == keyMap.end()) { targetKey = sourceElement->getMetaboliteKey(); } else targetKey = mapIt->second; newReac->addProduct(targetKey, sourceElement->getMultiplicity()); } jmax = sourceReac->getChemEq().getModifiers().size(); for (j = 0; j < jmax; ++j) { const CChemEqElement * sourceElement = &sourceReac->getChemEq().getModifiers()[j]; //check if the metab is in the map. If yes, translate it, otherwise not. mapIt = keyMap.find(sourceElement->getMetaboliteKey()); if (mapIt == keyMap.end()) { targetKey = sourceElement->getMetaboliteKey(); } else targetKey = mapIt->second; newReac->addModifier(targetKey); } //set the kinetic function newReac->setFunction(const_cast<CFunction*>(sourceReac->getFunction())); //mapping and local parameters for (j = 0; j < newReac->getFunctionParameters().size(); ++j) { switch (newReac->getFunctionParameters()[j]->getUsage()) { case CFunctionParameter::SUBSTRATE: case CFunctionParameter::PRODUCT: case CFunctionParameter::MODIFIER: //translate the metab keys { bool isVector = (newReac->getFunctionParameters()[j]->getType() == CFunctionParameter::VFLOAT64); //we assume that only SUBSTRATE, PRODUCT, MODIFIER can be vectors if (isVector) newReac->clearParameterMapping(j); size_t k; for (k = 0; k < sourceReac->getParameterMappings()[j].size(); ++k) { mapIt = keyMap.find(sourceReac->getParameterMappings()[j][k]); if (mapIt == keyMap.end()) { targetKey = sourceReac->getParameterMappings()[j][k]; } else targetKey = mapIt->second; if (isVector) newReac->addParameterMapping(j, targetKey); else newReac->setParameterMapping(j, targetKey); } } break; case CFunctionParameter::TIME: //just copy the key { mapIt = keyMap.find(sourceReac->getParameterMappings()[j][0]); if (mapIt == keyMap.end()) { targetKey = sourceReac->getParameterMappings()[j][0]; } else targetKey = mapIt->second; newReac->setParameterMapping(j, targetKey); } break; case CFunctionParameter::VOLUME: //translate the compartment key if necessary if (sourceReac->getParameterMappings()[j][0] == sourceComp->getKey()) newReac->setParameterMapping(j, keyMap[sourceComp->getKey()]); else { mapIt = keyMap.find(sourceReac->getParameterMappings()[j][0]); if (mapIt == keyMap.end()) { targetKey = sourceReac->getParameterMappings()[j][0]; } else targetKey = mapIt->second; newReac->setParameterMapping(j, targetKey); } //TODO: this needs to be adapted when sets of compartments will be copied break; case CFunctionParameter::PARAMETER: if (sourceReac->isLocalParameter(j)) newReac->setParameterValue(newReac->getFunctionParameters()[j]->getObjectName(), sourceReac->getParameterValue(newReac->getFunctionParameters()[j]->getObjectName())); else { mapIt = keyMap.find(sourceReac->getParameterMappings()[j][0]); if (mapIt == keyMap.end()) { targetKey = sourceReac->getParameterMappings()[j][0]; } else targetKey = mapIt->second; newReac->setParameterMapping(j, targetKey); } break; default: return info; break; } } } } } return true; }