void CModelExpansion::duplicateReaction(const CReaction* source, const std::string & index, const SetOfModelElements & sourceSet, ElementsMap & emap) { //if the source object has already been duplicated: do nothing if (emap.exists(source)) return; //try creating the object until we find a name that is not yet used CReaction* newObj; std::ostringstream infix; do { std::ostringstream name; name << source->getObjectName() << infix.str() << index; newObj = mpModel->createReaction(name.str()); infix << "_"; } while (!newObj); //add duplicated object to the map emap.add(source, newObj); //now copy the chemical equation size_t i; for (i = 0; i < source->getChemEq().getSubstrates().size(); ++i) { const CChemEqElement * sourceElement = source->getChemEq().getSubstrates()[i]; const CMetab* pMetab = NULL; if (sourceSet.contains(sourceElement->getMetabolite())) { if (!emap.exists(sourceElement->getMetabolite())) duplicateMetab(sourceElement->getMetabolite(), index, sourceSet, emap); pMetab = dynamic_cast<const CMetab*>(emap.getDuplicatePtr(sourceElement->getMetabolite())); } else //add the original metab { pMetab = sourceElement->getMetabolite(); } if (pMetab) newObj->addSubstrate(pMetab->getKey(), sourceElement->getMultiplicity()); } for (i = 0; i < source->getChemEq().getProducts().size(); ++i) { const CChemEqElement * sourceElement = source->getChemEq().getProducts()[i]; const CMetab* pMetab = NULL; if (sourceSet.contains(sourceElement->getMetabolite())) { if (!emap.exists(sourceElement->getMetabolite())) duplicateMetab(sourceElement->getMetabolite(), index, sourceSet, emap); pMetab = dynamic_cast<const CMetab*>(emap.getDuplicatePtr(sourceElement->getMetabolite())); } else //add the original metab { pMetab = sourceElement->getMetabolite(); } if (pMetab) newObj->addProduct(pMetab->getKey(), sourceElement->getMultiplicity()); } for (i = 0; i < source->getChemEq().getModifiers().size(); ++i) { const CChemEqElement * sourceElement = source->getChemEq().getModifiers()[i]; const CMetab* pMetab = NULL; if (sourceSet.contains(sourceElement->getMetabolite())) { if (!emap.exists(sourceElement->getMetabolite())) duplicateMetab(sourceElement->getMetabolite(), index, sourceSet, emap); pMetab = dynamic_cast<const CMetab*>(emap.getDuplicatePtr(sourceElement->getMetabolite())); } else //add the original metab { pMetab = sourceElement->getMetabolite(); } if (pMetab) newObj->addModifier(pMetab->getKey()); } newObj->setReversible(source->isReversible()); //set the kinetic function newObj->setFunction(const_cast<CFunction*>(source->getFunction())); //mapping and local parameters for (i = 0; i < newObj->getFunctionParameters().size(); ++i) { switch (newObj->getFunctionParameters()[i]->getUsage()) { case CFunctionParameter::SUBSTRATE: case CFunctionParameter::PRODUCT: case CFunctionParameter::MODIFIER: { bool isVector = (newObj->getFunctionParameters()[i]->getType() == CFunctionParameter::VFLOAT64); if (isVector) newObj->clearParameterMapping(i); size_t k; for (k = 0; k < source->getParameterMappings()[i].size(); ++k) { //we assume that by now the metab was copied if necessary. //therefore we only need to check the map. std::string targetKey; if (emap.exists(source->getParameterMappings()[i][k])) targetKey = emap.getDuplicateKey(source->getParameterMappings()[i][k]); else targetKey = source->getParameterMappings()[i][k]; if (isVector) newObj->addParameterMapping(i, targetKey); else newObj->setParameterMapping(i, targetKey); } } break; case CFunctionParameter::TIME: newObj->setParameterMapping(i, source->getParameterMappings()[i][0]); break; case CFunctionParameter::VOLUME: if (sourceSet.contains(source->getParameterMappings()[i][0])) { if (!emap.exists(source->getParameterMappings()[i][0])) { const CCompartment* pSource = dynamic_cast<const CCompartment*>( (CCopasiRootContainer::getKeyFactory()->get(source->getParameterMappings()[i][0]))); duplicateCompartment(pSource, index, sourceSet, emap); } newObj->setParameterMapping(i, emap.getDuplicateKey(source->getParameterMappings()[i][0])); } else //add the original metab { newObj->setParameterMapping(i, source->getParameterMappings()[i][0]); } break; case CFunctionParameter::PARAMETER: if (newObj->isLocalParameter(i)) { //just copy the value newObj->setParameterValue(newObj->getFunctionParameters()[i]->getObjectName(), source->getParameterValue(newObj->getFunctionParameters()[i]->getObjectName())); } else { if (sourceSet.contains(source->getParameterMappings()[i][0])) { if (!emap.exists(source->getParameterMappings()[i][0])) { const CModelValue* pSource = dynamic_cast<const CModelValue*>( (CCopasiRootContainer::getKeyFactory()->get(source->getParameterMappings()[i][0]))); duplicateGlobalQuantity(pSource, index, sourceSet, emap); } newObj->setParameterMapping(i, emap.getDuplicateKey(source->getParameterMappings()[i][0])); } else //add the original global quantity { newObj->setParameterMapping(i, source->getParameterMappings()[i][0]); } } break; default: break; } } newObj->setNotes(source->getNotes()); newObj->setMiriamAnnotation(source->getMiriamAnnotation(), newObj->getKey(), source->getKey()); }
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; }