//static CLayout * SBMLDocumentLoader::createLayout(const Layout & sbmlLayout, const std::map<std::string, std::string> & modelmap, std::map<std::string, std::string> & layoutmap #ifdef USE_CRENDER_EXTENSION , const std::map<std::string, std::string>& globalIdToKeyMap //,const std::map<std::string,std::map<std::string,std::string> >& globalColorIdToKeyMapMap //,const std::map<std::string,std::map<std::string,std::string> >& globalGradientIdToKeyMapMap //,const std::map<std::string,std::map<std::string,std::string> >& globalLineEndingIdToKeyMapMap #endif /* USE_CRENDER_EXTENSION */ , const CCopasiContainer * pParent ) { CLayout* layout = new CLayout(sbmlLayout, layoutmap, pParent); //compartments unsigned C_INT32 i, iMax = sbmlLayout.getListOfCompartmentGlyphs()->size(); for (i = 0; i < iMax; ++i) { const CompartmentGlyph* tmp = dynamic_cast<const CompartmentGlyph*>(sbmlLayout.getListOfCompartmentGlyphs()->get(i)); if (tmp) layout->addCompartmentGlyph(new CLCompartmentGlyph(*tmp, modelmap, layoutmap)); } //species iMax = sbmlLayout.getListOfSpeciesGlyphs()->size(); for (i = 0; i < iMax; ++i) { const SpeciesGlyph* tmp = dynamic_cast<const SpeciesGlyph*>(sbmlLayout.getListOfSpeciesGlyphs()->get(i)); if (tmp) layout->addMetaboliteGlyph(new CLMetabGlyph(*tmp, modelmap, layoutmap)); } //reactions iMax = sbmlLayout.getListOfReactionGlyphs()->size(); for (i = 0; i < iMax; ++i) { const ReactionGlyph* tmp = dynamic_cast<const ReactionGlyph*>(sbmlLayout.getListOfReactionGlyphs()->get(i)); if (tmp) layout->addReactionGlyph(new CLReactionGlyph(*tmp, modelmap, layoutmap)); } //text iMax = sbmlLayout.getListOfTextGlyphs()->size(); for (i = 0; i < iMax; ++i) { const TextGlyph* tmp = dynamic_cast<const TextGlyph*>(sbmlLayout.getListOfTextGlyphs()->get(i)); if (tmp) layout->addTextGlyph(new CLTextGlyph(*tmp, modelmap, layoutmap)); } //additional iMax = sbmlLayout.getListOfAdditionalGraphicalObjects()->size(); for (i = 0; i < iMax; ++i) { const GraphicalObject* graphical = dynamic_cast<const GraphicalObject*>(sbmlLayout.getListOfAdditionalGraphicalObjects()->get(i)); if (graphical) layout->addGeneralGlyph(new CLGeneralGlyph(*graphical, modelmap, layoutmap)); } //second pass text (the text glyph can refer to other glyphs. These references can) //only be resolved after all glyphs are created). iMax = sbmlLayout.getListOfTextGlyphs()->size(); for (i = 0; i < iMax; ++i) { const TextGlyph* tmp = dynamic_cast<const TextGlyph*>(sbmlLayout.getListOfTextGlyphs()->get(i)); if (tmp) postprocessTextGlyph(*tmp, layoutmap); } #ifdef USE_CRENDER_EXTENSION RenderLayoutPlugin* rlPlugin = (RenderLayoutPlugin*) sbmlLayout.getPlugin("render"); assert(rlPlugin != NULL); // import the local render information iMax = rlPlugin->getNumLocalRenderInformationObjects(); std::map<std::string, std::string> idToKeyMap; CLLocalRenderInformation* pLRI = NULL; //std::map<std::string,std::string> colorIdToKeyMap; //std::map<std::string,std::string> gradientIdToKeyMap; //std::map<std::string,std::string> lineEndingIdToKeyMap; //std::map<std::string,std::map<std::string,std::string> > colorIdToKeyMapMap; //std::map<std::string,std::map<std::string,std::string> > gradientIdToKeyMapMap; //std::map<std::string,std::map<std::string,std::string> > lineEndingIdToKeyMapMap; for (i = 0; i < iMax; ++i) { //colorIdToKeyMap.clear(); //gradientIdToKeyMap.clear(); //lineEndingIdToKeyMap.clear(); //pLRI=new CLLocalRenderInformation(*sbmlLayout.getRenderInformation(i),colorIdToKeyMap,gradientIdToKeyMap,lineEndingIdToKeyMap,layout); pLRI = new CLLocalRenderInformation(*rlPlugin->getRenderInformation(i), layout); if (rlPlugin->getRenderInformation(i)->isSetId()) idToKeyMap.insert(std::pair<std::string, std::string>(rlPlugin->getRenderInformation(i)->getId(), pLRI->getKey())); else idToKeyMap.insert(std::pair<std::string, std::string>(pLRI->getKey(), pLRI->getKey())); //colorIdToKeyMapMap.insert(std::pair<std::string,std::map<std::string,std::string> >(pLRI->getKey(),colorIdToKeyMap)); //gradientIdToKeyMapMap.insert(std::pair<std::string,std::map<std::string,std::string> >(pLRI->getKey(),gradientIdToKeyMap)); //lineEndingIdToKeyMapMap.insert(std::pair<std::string,std::map<std::string,std::string> >(pLRI->getKey(),lineEndingIdToKeyMap)); // fix the references to layout objects in id lists size_t j, jMax = pLRI->getNumStyles(); for (j = 0; j < jMax; j++) { SBMLDocumentLoader::convertLayoutObjectIds(*(pLRI->getStyle(j)), layoutmap); } layout->addLocalRenderInformation(pLRI); } // fix the references // we have to consider the global ids as well // since all ids in these two map should be unique, we can just combine them size_t count = idToKeyMap.size() + globalIdToKeyMap.size(); idToKeyMap.insert(globalIdToKeyMap.begin(), globalIdToKeyMap.end()); // make sure the ids were really unique assert(idToKeyMap.size() == count); SBMLDocumentLoader::convertRenderInformationReferencesIds<CLLocalRenderInformation>(layout->getListOfLocalRenderInformationObjects(), idToKeyMap); // fix the color ids, gradient ids and line ending ids. /* std::map<std::string,std::map<std::string,std::string> >::const_iterator mapPos; std::map<std::string,std::map<std::string,std::string> > expandedColorIdToKeyMapMap, expandedGradientIdToKeyMapMap, expandedLineEndingIdToKeyMapMap; for(i=0;i < iMax; ++i) { pLRI=dynamic_cast<CLLocalRenderInformation*>(layout->getRenderInformation(i)); assert(pLRI != NULL); std::set<std::string> chain; SBMLDocumentLoader::expandIdToKeyMaps<CLLocalRenderInformation>(pLRI, layout->getListOfLocalRenderInformationObjects(), expandedColorIdToKeyMapMap, expandedGradientIdToKeyMapMap, expandedLineEndingIdToKeyMapMap, colorIdToKeyMapMap, gradientIdToKeyMapMap, lineEndingIdToKeyMapMap, chain, globalColorIdToKeyMapMap, globalGradientIdToKeyMapMap, globalLineEndingIdToKeyMapMap ); SBMLDocumentLoader::convertPropertyKeys<CLLocalRenderInformation>(pLRI,expandedColorIdToKeyMapMap[pLRI->getKey()],expandedGradientIdToKeyMapMap[pLRI->getKey()],expandedLineEndingIdToKeyMapMap[pLRI->getKey()]); } */ #endif /* USE_CRENDER_EXTENSION */ return layout; }
CLayout* CCopasiSpringLayout::createLayout( CDataContainer *parent, const std::set<const CCompartment*>& compartments, const std::set<const CReaction*>& reactions, const std::set<const CMetab*>& metabs, const std::set<const CMetab*>& sideMetabs, Parameters* mParams ) { CLayout *pResult = new CLayout("Layout", parent); double fontSize = 16.0; double fontHeight = fontSize * 1.5; // create a species glyph for each species in metabs std::map<const CCompartment*, CompartmentInfo> compInfo; std::map<const CMetab*, CLMetabGlyph*> metabMap; std::set<const CMetab*>::const_iterator metabIt; for (metabIt = metabs.begin(); metabIt != metabs.end(); ++metabIt) { if (sideMetabs.find(*metabIt) != sideMetabs.end()) continue; //estimate the size of the glyph double width = (double)((*metabIt)->getObjectName().length() * fontSize); double height = (double)fontHeight; if (width < height) { width = height; } //create the glyph CLMetabGlyph* pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4)); pMetabGlyph->setModelObjectKey((*metabIt)->getKey()); pResult->addMetaboliteGlyph(pMetabGlyph); metabMap[*metabIt] = pMetabGlyph; //create the text glyph for the label CLTextGlyph* pTextGlyph = new CLTextGlyph; pTextGlyph->setDimensions(CLDimensions(width, height)); pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey()); pTextGlyph->setModelObjectKey((*metabIt)->getKey()); pResult->addTextGlyph(pTextGlyph); //add up the sizes for the compartment const CCompartment* pComp = NULL; if (compartments.find((*metabIt)->getCompartment()) != compartments.end()) pComp = (*metabIt)->getCompartment(); compInfo[pComp].add((width + 4) * (height + 4)); } //now the reaction glyphs std::set<const CReaction*>::const_iterator reactIt; for (reactIt = reactions.begin(); reactIt != reactions.end(); ++reactIt) { CLReactionGlyph* pReactionGlyph = new CLReactionGlyph; //pResult->setDimensions(CLDimensions(width, height)); pReactionGlyph->setModelObjectKey((*reactIt)->getKey()); //pReactionGlyph->getCurve().addCurveSegment(CLLineSegment(CLPoint(x, y), // CLPoint(x + length, y))); bool isReversible = (*reactIt)->isReversible(); pResult->addReactionGlyph(pReactionGlyph); //now add the species reference glyphs. //substrates const CDataVector < CChemEqElement >& substrates = (*reactIt)->getChemEq().getSubstrates(); bool substrateExists = false; CDataVector<CChemEqElement>::const_iterator elIt; for (elIt = substrates.begin(); elIt != substrates.end(); ++elIt) { const CMetab* pMetab = elIt->getMetabolite(); if (!pMetab) continue; CLMetabGlyph* pMetabGlyph = NULL; CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE; CLMetabReferenceGlyph::Role functionalRole; //is it a side reactant? If yes, create a new metab glyph if (sideMetabs.find(pMetab) != sideMetabs.end()) { //estimate the size of the glyph double width = (double)((pMetab)->getObjectName().length() * fontSize); double height = (double)fontHeight; if (width < height) { width = height; } //create the glyph pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4)); pMetabGlyph->setModelObjectKey(pMetab->getKey()); //TODO: mark as duplicate pResult->addMetaboliteGlyph(pMetabGlyph); //create the text glyph for the label CLTextGlyph* pTextGlyph = new CLTextGlyph; pTextGlyph->setDimensions(CLDimensions(width, height)); pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey()); pTextGlyph->setModelObjectKey(pMetab->getKey()); pResult->addTextGlyph(pTextGlyph); //add up the sizes for the compartment const CCompartment* pComp = NULL; if (compartments.find(pMetab->getCompartment()) != compartments.end()) pComp = pMetab->getCompartment(); compInfo[pComp].add((width + 4) * (height + 4)); role = isReversible ? CLMetabReferenceGlyph::SIDEPRODUCT : CLMetabReferenceGlyph::SIDESUBSTRATE; functionalRole = CLMetabReferenceGlyph::SIDESUBSTRATE; } else { //find the existing metab glyph std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt; mmIt = metabMap.find(pMetab); if (mmIt != metabMap.end()) pMetabGlyph = mmIt->second; role = isReversible ? CLMetabReferenceGlyph::PRODUCT : CLMetabReferenceGlyph::SUBSTRATE; functionalRole = CLMetabReferenceGlyph::SUBSTRATE; } if (!pMetabGlyph) continue; CLMetabReferenceGlyph* pRefGlyph = new CLMetabReferenceGlyph; //pResult->setModelObjectKey(modelobjectkey); pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole(role); pRefGlyph->setFunctionalRole(functionalRole); pReactionGlyph->addMetabReferenceGlyph(pRefGlyph); substrateExists = true; } //substrates // if we have no substrates, add a dummy / invisible node for now if (!substrateExists) { CLMetabGlyph* pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(1, 1)); pMetabGlyph->setObjectRole("invisible"); pResult->addMetaboliteGlyph(pMetabGlyph); CLMetabReferenceGlyph* pRefGlyph = new CLMetabReferenceGlyph; //pResult->setModelObjectKey(modelobjectkey); pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole(CLMetabReferenceGlyph::SUBSTRATE); //TODO side substr? pRefGlyph->setFunctionalRole(CLMetabReferenceGlyph::SUBSTRATE); pReactionGlyph->addMetabReferenceGlyph(pRefGlyph); } //products const CDataVector < CChemEqElement >& products = (*reactIt)->getChemEq().getProducts(); bool productExists = false; for (elIt = products.begin(); elIt != products.end(); ++elIt) { const CMetab* pMetab = elIt->getMetabolite(); if (!pMetab) continue; CLMetabGlyph* pMetabGlyph = NULL; CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE; CLMetabReferenceGlyph::Role functionalRole; //is it a side reactant? If yes, create a new metab glyph if (sideMetabs.find(pMetab) != sideMetabs.end()) { //estimate the size of the glyph double width = (double)((pMetab)->getObjectName().length() * fontSize); double height = (double)fontHeight; if (width < height) { width = height; } //create the glyph pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4)); pMetabGlyph->setModelObjectKey(pMetab->getKey()); //TODO: mark as duplicate pResult->addMetaboliteGlyph(pMetabGlyph); //create the text glyph for the label CLTextGlyph* pTextGlyph = new CLTextGlyph; pTextGlyph->setDimensions(CLDimensions(width, height)); pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey()); pTextGlyph->setModelObjectKey(pMetab->getKey()); pResult->addTextGlyph(pTextGlyph); //add up the sizes for the compartment const CCompartment* pComp = NULL; if (compartments.find(pMetab->getCompartment()) != compartments.end()) pComp = pMetab->getCompartment(); compInfo[pComp].add((width + 4) * (height + 4)); role = CLMetabReferenceGlyph::SIDEPRODUCT; functionalRole = CLMetabReferenceGlyph::SIDEPRODUCT; } else { //find the existing metab glyph std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt; mmIt = metabMap.find(pMetab); if (mmIt != metabMap.end()) pMetabGlyph = mmIt->second; role = CLMetabReferenceGlyph::PRODUCT; functionalRole = CLMetabReferenceGlyph::PRODUCT; } if (!pMetabGlyph) continue; CLMetabReferenceGlyph* pRefGlyph = new CLMetabReferenceGlyph; //pResult->setModelObjectKey(modelobjectkey); pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole(role); pRefGlyph->setFunctionalRole(functionalRole); pReactionGlyph->addMetabReferenceGlyph(pRefGlyph); productExists = true; } //products // if we have no substrates, add a dummy / invisible node for now if (!productExists) { CLMetabGlyph* pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(1, 1)); pMetabGlyph->setObjectRole("invisible"); pResult->addMetaboliteGlyph(pMetabGlyph); CLMetabReferenceGlyph* pRefGlyph = new CLMetabReferenceGlyph; //pResult->setModelObjectKey(modelobjectkey); pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole(CLMetabReferenceGlyph::PRODUCT); //TODO side substr? pReactionGlyph->addMetabReferenceGlyph(pRefGlyph); } //modifiers const CDataVector < CChemEqElement >& modifiers = (*reactIt)->getChemEq().getModifiers(); for (elIt = modifiers.begin(); elIt != modifiers.end(); ++elIt) { const CMetab* pMetab = elIt->getMetabolite(); if (!pMetab) continue; CLMetabGlyph* pMetabGlyph = NULL; CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE; //is it a side reactant? If yes, create a new metab glyph if (sideMetabs.find(pMetab) != sideMetabs.end()) { //estimate the size of the glyph double width = (double)((pMetab)->getObjectName().length() * fontSize); double height = (double)fontHeight; if (width < height) { width = height; } //create the glyph pMetabGlyph = new CLMetabGlyph; pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4)); pMetabGlyph->setModelObjectKey(pMetab->getKey()); //TODO: mark as duplicate pResult->addMetaboliteGlyph(pMetabGlyph); //create the text glyph for the label CLTextGlyph* pTextGlyph = new CLTextGlyph; pTextGlyph->setDimensions(CLDimensions(width, height)); pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey()); pTextGlyph->setModelObjectKey(pMetab->getKey()); pResult->addTextGlyph(pTextGlyph); //add up the sizes for the compartment const CCompartment* pComp = NULL; if (compartments.find(pMetab->getCompartment()) != compartments.end()) pComp = pMetab->getCompartment(); compInfo[pComp].add((width + 4) * (height + 4)); role = CLMetabReferenceGlyph::MODIFIER; //TODO SIDEMODIFIER??? } else { //find the existing metab glyph std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt; mmIt = metabMap.find(pMetab); if (mmIt != metabMap.end()) pMetabGlyph = mmIt->second; role = CLMetabReferenceGlyph::MODIFIER; } if (!pMetabGlyph) continue; CLMetabReferenceGlyph* pRefGlyph = new CLMetabReferenceGlyph; //pResult->setModelObjectKey(modelobjectkey); pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole(role); pReactionGlyph->addMetabReferenceGlyph(pRefGlyph); } //modifiers } //reactions //rules size_t i; for (i = 0; i < pResult->getListOfMetaboliteGlyphs().size(); ++i) { const CLMetabGlyph* pMetabGlyph = &pResult->getListOfMetaboliteGlyphs()[i]; const CMetab* pMetab = dynamic_cast<const CMetab*>(pMetabGlyph->getModelObject()); if (!pMetab) continue; if (pMetab->getStatus() == CModelEntity::Status::ODE || pMetab->getStatus() == CModelEntity::Status::ASSIGNMENT) { CLGeneralGlyph* pGG = new CLGeneralGlyph; pGG->setDimensions(CLDimensions(10, 10)); pGG->setObjectRole("rule"); pResult->addGeneralGlyph(pGG); CLReferenceGlyph* pRefGlyph = new CLReferenceGlyph; pRefGlyph->setDimensions(CLDimensions(10, 10)); pRefGlyph->setTargetGlyphKey(pMetabGlyph->getKey()); pRefGlyph->setRole("rule connection"); pGG->addReferenceGlyph(pRefGlyph); } } //after all other glyphs are created, create the compartment glyphs double xxx = 0; std::set<const CCompartment*>::const_iterator compIt; for (compIt = compartments.begin(); compIt != compartments.end(); ++compIt) { double compSize = 10000; std::map<const CCompartment*, CompartmentInfo>::const_iterator ccIt; ccIt = compInfo.find(*compIt); if (ccIt != compInfo.end()) { //some glyphs are placed inside this compartment glyph compSize = ccIt->second.mAreaSum * 40; } //create the glyph CLCompartmentGlyph* pCompGlyph = new CLCompartmentGlyph; pCompGlyph->setModelObjectKey((*compIt)->getKey()); pCompGlyph->setDimensions(CLDimensions(CLDimensions(sqrt(compSize), sqrt(compSize)))); pCompGlyph->setPosition(CLPoint(xxx, 5)); xxx += sqrt(compSize) + 10; pResult->addCompartmentGlyph(pCompGlyph); } // // double sss = sqrt(compInfo[NULL].mAreaSum * 40); // // // determine and set the layout dimensions // CLBoundingBox box = pResult->calculateBoundingBox(); // if (box.getDimensions().getWidth() < sss) // box.getDimensions().setWidth(sss); // // if (box.getDimensions().getHeight() < sss) // box.getDimensions().setHeight(sss); // // pResult->setDimensions(CLDimensions(box.getDimensions().getWidth() + 30.0, box.getDimensions().getHeight() + 30.0)); // randomize CCopasiSpringLayout l(pResult, mParams); l.randomize(); // determine and set the layout dimensions CLBoundingBox box = pResult->calculateBoundingBox(); pResult->setDimensions(CLDimensions(box.getDimensions().getWidth() + 30.0, box.getDimensions().getHeight() + 30.0)); return pResult; }