Exemplo n.º 1
0
double CCopasiSpringLayout::potSpeciesReaction(const CLMetabGlyph & a, const CLReactionGlyph & b) const
{
  double tmp = bound_distance(a.getX() + a.getWidth() / 2, a.getY() + a.getHeight() / 2,
                              b.getX() + b.getWidth() / 2, b.getY() + b.getHeight() / 2, 200);

  if (tmp < 1) tmp = 1;

  return /*a.charge*b.charge*/ 1 / tmp; //TODO: reintroduce the charge
}
Exemplo n.º 2
0
double CCopasiSpringLayout::potReactionCompartment(const CLReactionGlyph & r, const CLCompartmentGlyph & c) const
{
  double tmp = 0;
  double dist = fabs((r.getX() + 0.5 * r.getWidth()) - (c.getX() + 0.5 * c.getWidth()));

  if (dist > (0.5 * c.getWidth() - 50))
    tmp += pow(dist - 0.5 * c.getWidth() + 50, 2);

  dist = fabs((r.getY() + 0.5 * r.getHeight()) - (c.getY() + 0.5 * c.getHeight()));

  if (dist > (0.5 * c.getHeight() - 50))
    tmp += pow(dist - 0.5 * c.getHeight() + 50, 2);

  return tmp /**s.charge*/; //TODO reintroduce charge
}
Exemplo n.º 3
0
double CCopasiSpringLayout::potEdge(const CLMetabReferenceGlyph & e, const CLReactionGlyph & r) const
{
  double dist = 70;

  if (e.getRole() == CLMetabReferenceGlyph::SIDESUBSTRATE || e.getRole() == CLMetabReferenceGlyph::SIDEPRODUCT)
    dist = 40;

  const CLMetabGlyph * pMG = e.getMetabGlyph();
  double tmp = distance(pMG->getX() + pMG->getWidth() / 2, pMG->getY() + pMG->getHeight() / 2,
                        r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2);

  if (e.getRole() == CLMetabReferenceGlyph::MODIFIER)
    return 0.3 * pow(tmp - dist, 2);
  else
    return pow(tmp - dist, 2);
}
Exemplo n.º 4
0
double CCopasiSpringLayout::getPotential()
{
  //here we need to add the different effects that contribute to the potential

  double tmp = 0;

  //repulsion between species nodes
  unsigned int i, j;

  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size() - 1; ++i)
    for (j = i + 1; j < mpLayout->getListOfMetaboliteGlyphs().size(); ++j)
      {
        if (i != j)
          tmp += 100000 * potSpeciesSpecies(*mpLayout->getListOfMetaboliteGlyphs()[i], *mpLayout->getListOfMetaboliteGlyphs()[j]);
      }

  // only if we have reactions!
  if (mpLayout->getListOfReactionGlyphs().size() > 0)
    {
      //repulsion between species nodes and reaction nodes
      for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
        for (j = 0; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
          {
            tmp += 100000 * potSpeciesReaction(*mpLayout->getListOfMetaboliteGlyphs()[i], *mpLayout->getListOfReactionGlyphs()[j]);
          }

      //repulsion between reaction nodes
      for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() - 1; ++i)
        for (j = i + 1; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
          {
            if (i != j)
              tmp += 100000 * potReactionReaction(*mpLayout->getListOfReactionGlyphs()[i], *mpLayout->getListOfReactionGlyphs()[j]);
          }
    }

  //spring force for species references
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
    {
      CLReactionGlyph* pRG = mpLayout->getListOfReactionGlyphs()[i];

      for (j = 0; j < pRG->getListOfMetabReferenceGlyphs().size(); ++j)
        {
          tmp += 0.5 * potEdge(*pRG->getListOfMetabReferenceGlyphs()[j], *pRG);
        }
    }

  /*
      //forces at reaction nodes
      for (i=0; i<mReactionNodes.size(); ++i)
        {
          tmp += 3000* potReaction(mReactionNodes[i]);
        }
  */

  //force to keep species in compartment
  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
    {
      CLMetabGlyph* tmpMG = mpLayout->getListOfMetaboliteGlyphs()[i];
      std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpMG);

      if (mapIt == mCompartmentMap.end())
        {
          //there is no information in the map. Should not happen.
#ifdef COPASI_DEBUG
          std::cout << "No compartment info for a species glyph!!!" << std::endl;
#endif
          continue;
        }

      CLCompartmentGlyph* tmpCG = mapIt->second;

      if (tmpCG) //the species glyph is inside a compartment glyph
        tmp += 0.2 * potSpeciesCompartment(*tmpMG, *tmpCG);
    }

  //force to keep reaction nodes in compartment
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
    {
      CLReactionGlyph* tmpRG = mpLayout->getListOfReactionGlyphs()[i];
      std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpRG);

      if (mapIt == mCompartmentMap.end())
        {
          //there is no information in the map. Should not happen.
#ifdef COPASI_DEBUG
          std::cout << "No compartment info for a reaction glyph!!!" << std::endl;
#endif
          continue;
        }

      CLCompartmentGlyph* tmpCG = mapIt->second;

      if (tmpCG) //the reaction glyph is inside a compartment glyph
        tmp += 0.2 * potReactionCompartment(*tmpRG, *tmpCG);
    }

  /*

    //force to shrink compartments
    for (i=0; i<mCompartmentNodes.size(); ++i)
      {
        tmp += 0.2*(fabs(mCompartmentNodes[i].w-100)+fabs(mCompartmentNodes[i].h-100));
      }

    //repulsion between compartments
    for (i=0; i<mCompartmentNodes.size(); ++i)
    for (j=0; j<mCompartmentNodes.size(); ++j)
      {
        if (i!=j)
          tmp += 100*potCompartmentCompartment(mCompartmentNodes[i], mCompartmentNodes[j]);
      }

    //centering force
    for (i=0; i<mCompartmentNodes.size(); ++i)
      {
        tmp += 10*(fabs(mCompartmentNodes[i].x)+fabs(mCompartmentNodes[i].y));
      }
    */
  return tmp;
}
Exemplo n.º 5
0
void CCopasiSpringLayout::finalizeState()
{
  unsigned int i;

  //update the positions of the dependent glyphs
  //this can be done here since we assume that those glyphs
  //do not affect the layout.
  std::vector<CoordinateRelation>::const_iterator it, itEnd = mFixedRelations.end();

  for (it = mFixedRelations.begin(); it != itEnd; ++it)
    it->target->setPosition(it->source->getPosition() + it->diff);

  //for now, only create curves for the reaction glyphs
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
    {
      CLReactionGlyph* pRG = mpLayout->getListOfReactionGlyphs()[i];

      //Determine the average position of substrates and products, giving less weight to side reactants
      CLPoint s, p;
      double s_c = 0; double p_c = 0;
      unsigned int j, jmax = pRG->getListOfMetabReferenceGlyphs().size();

      for (j = 0; j < jmax; ++j)
        {
          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SUBSTRATE)
            {
              s_c += 1.0;
              s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SIDESUBSTRATE)
            {
              s_c += 0.1;
              s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::PRODUCT)
            {
              p_c += 1.0;
              p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SIDEPRODUCT)
            {
              p_c += 0.1;
              p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
            }
        }

      if (s_c > 0)
        s = s * (1 / s_c);
      else
        s = pRG->getPosition();

      if (p_c > 0)
        p = p * (1 / p_c);
      else
        p = pRG->getPosition();

      CLPoint dir = p - s; //overall direction of reaction

      if (dir.getX() == 0 && dir.getY() == 0)
        dir = CLPoint(1, 0);

      CLPoint ortho_dir = CLPoint(dir.getY(), -dir.getX());
      ortho_dir.scale(1 / sqrt(pow(ortho_dir.getX(), 2) + pow(ortho_dir.getY(), 2)));

      CLPoint reaction_s = pRG->getPosition() - (dir * 0.05);
      CLPoint reaction_p = pRG->getPosition() + (dir * 0.05);
      CLPoint reaction_m1 = pRG->getPosition() + ortho_dir * 10;
      CLPoint reaction_m2 = pRG->getPosition() - ortho_dir * 10;

      pRG->getCurve().clear();
      pRG->getCurve().addCurveSegment(CLLineSegment(reaction_s, reaction_p));

      for (j = 0; j < jmax; ++j)
        {
          //here we need to generate the curves for the MetabReferenceGlyphs.
          //we will need to consider the size of the glyphs, role of the metab in the reaction, etc.
          //For now, only a primitive implementation: TODO: improve
          CLMetabReferenceGlyph* pMRG = pRG->getListOfMetabReferenceGlyphs()[j];
          double direction;
          double modifierLength = -0.2;

          switch (pMRG->getRole())
            {
              case CLMetabReferenceGlyph::SUBSTRATE :
              case CLMetabReferenceGlyph::SIDESUBSTRATE :
              {
                direction = -0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_s + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_s,
                                                 metabPoint,
                                                 reaction_s + dir * direction,
                                                 (reaction_s + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              case CLMetabReferenceGlyph::PRODUCT :
              case CLMetabReferenceGlyph::SIDEPRODUCT :
              {
                direction = 0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_p + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_p,
                                                 metabPoint,
                                                 reaction_p + dir * direction,
                                                 (reaction_p + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              default:
              {
                CLPoint reactionPoint;

                if (ortho_dir.dot(pRG->getPosition() - pMRG->getMetabGlyph()->getPosition()) < 0)
                  {
                    direction = +10.0;
                    reactionPoint = reaction_m1;
                  }
                else
                  {
                    direction = -10.0;
                    reactionPoint = reaction_m2;
                  }

                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reactionPoint + dir * 0 * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(metabPoint,
                                                 reactionPoint,
                                                 (reactionPoint + dir * (0 * direction * 1.5) + metabPoint) * 0.5,
                                                 reactionPoint + ortho_dir * direction));
              }
            }
        }
    }

  //rearrange the text boxes
  //TODO

  //calculate bounding box for the layout, or recenter the layout
  //for (i = 0; i < mpLayout->getListOfSpeciesGlyphs().size() ; ++i)

  const CLBoundingBox &bounds =  mpLayout->calculateBoundingBox();

  mpLayout->setDimensions(CLDimensions(bounds.getPosition().getX() + bounds.getDimensions().getWidth(), bounds.getPosition().getY() + bounds.getDimensions().getHeight()));
}
Exemplo n.º 6
0
void CLayout::exportToSBML(Layout * layout, const std::map<CCopasiObject*, SBase*> & copasimodelmap,
                           std::map<std::string, const SBase*>& sbmlIDs) const
{
  if (!layout) return;

  //Name and ID
  std::string id = CSBMLExporter::createUniqueId(sbmlIDs, "layout_");
  layout->setId(id);
  sbmlIDs.insert(std::pair<const std::string, const SBase*>(id, layout));
  //we do not check if the layout is already present in the libsbml data
  //structures. This is no big deal since at the moment no software
  //relies on persistent IDs for layout elements.

  //Dimensions
  Dimensions tmpDim = mDimensions.getSBMLDimensions();
  layout->setDimensions(&tmpDim);

  //some of the following code is not used at the moment:  the COPASI model map
  //does not contain glyphs. Since this may change in the future I leave the code
  //below.

  // create a map from COPASI layout object to SBML objects. We do not put
  //the layout objects into the global map (copasimodelmap) but we need to have
  //access to all objects in the current layout since speciesReferenceGlyph and
  //textGlyph need to reference other graphical objects.
  std::map<const CLBase*, const SBase*> layoutmap;

  //Compartment glyphs
  unsigned C_INT32 i, imax = mvCompartments.size();

  for (i = 0; i < imax; ++i)
    {
      CLCompartmentGlyph * tmp = mvCompartments[i];

      //check if the compartment glyph exists in the libsbml data
      std::map<CCopasiObject*, SBase*>::const_iterator it;
      it = copasimodelmap.find(tmp);

      CompartmentGlyph * pCG;

      if (it == copasimodelmap.end()) //not found
        {
          pCG = new CompartmentGlyph;
          layout->getListOfCompartmentGlyphs()->appendAndOwn(pCG);
        }
      else
        {
          pCG = dynamic_cast<CompartmentGlyph*>(it->second);
        }

      layoutmap.insert(std::pair<const CLBase*, const SBase*>(tmp, pCG));
      tmp->exportToSBML(pCG, copasimodelmap, sbmlIDs);
    }

  //Species glyphs
  imax = mvMetabs.size();

  for (i = 0; i < imax; ++i)
    {
      CLMetabGlyph * tmp = mvMetabs[i];

      //check if the glyph exists in the libsbml data
      std::map<CCopasiObject*, SBase*>::const_iterator it;
      it = copasimodelmap.find(tmp);

      SpeciesGlyph * pG;

      if (it == copasimodelmap.end()) //not found
        {
          pG = new SpeciesGlyph;
          layout->getListOfSpeciesGlyphs()->appendAndOwn(pG);
        }
      else
        {
          pG = dynamic_cast<SpeciesGlyph*>(it->second);
        }

      layoutmap.insert(std::pair<const CLBase*, const SBase*>(tmp, pG));
      tmp->exportToSBML(pG, copasimodelmap, sbmlIDs);
    }

  //Reaction glyphs
  imax = mvReactions.size();

  for (i = 0; i < imax; ++i)
    {
      CLReactionGlyph * tmp = mvReactions[i];

      //check if the glyph exists in the libsbml data
      std::map<CCopasiObject*, SBase*>::const_iterator it;
      it = copasimodelmap.find(tmp);

      ReactionGlyph * pG;

      if (it == copasimodelmap.end()) //not found
        {
          pG = new ReactionGlyph;
          layout->getListOfReactionGlyphs()->appendAndOwn(pG);
        }
      else
        {
          pG = dynamic_cast<ReactionGlyph*>(it->second);
        }

      layoutmap.insert(std::pair<const CLBase*, const SBase*>(tmp, pG));
      //we need to pass the layoutmap here for 2 reasons:
      //1. the metabreferenceglyphs need to be added
      //2. the metabreferenceglyphs need to resolve the reference to the metabglyph
      tmp->exportToSBML(pG, copasimodelmap, sbmlIDs, layoutmap);
    }

  //Text glyphs
  imax = mvLabels.size();

  for (i = 0; i < imax; ++i)
    {
      CLTextGlyph * tmp = mvLabels[i];

      //check if the glyph exists in the libsbml data
      std::map<CCopasiObject*, SBase*>::const_iterator it;
      it = copasimodelmap.find(tmp);

      TextGlyph * pG;

      if (it == copasimodelmap.end()) //not found
        {
          pG = new TextGlyph;
          layout->getListOfTextGlyphs()->appendAndOwn(pG);
        }
      else
        {
          pG = dynamic_cast<TextGlyph*>(it->second);
        }

      layoutmap.insert(std::pair<const CLBase*, const SBase*>(tmp, pG));
      tmp->exportToSBML(pG, copasimodelmap, sbmlIDs);
    }

  //generic glyphs
  imax = mvGraphicalObjects.size();

  for (i = 0; i < imax; ++i)
    {
      CLGraphicalObject * tmp = mvGraphicalObjects[i];

      //check if the glyph exists in the libsbml data
      std::map<CCopasiObject*, SBase*>::const_iterator it;
      it = copasimodelmap.find(tmp);

      GraphicalObject * pG;

      if (it == copasimodelmap.end()) //not found
        {
          pG = new GraphicalObject;
          layout->getListOfAdditionalGraphicalObjects()->appendAndOwn(pG);
        }
      else
        {
          pG = dynamic_cast<GraphicalObject*>(it->second);
        }

      layoutmap.insert(std::pair<const CLBase*, const SBase*>(tmp, pG));
      tmp->exportToSBML(pG, copasimodelmap, sbmlIDs);
    }

  //now that we have all graphical objects in the layoutmap we can resolve the references
  //in the text glyphs
  imax = mvLabels.size();

  for (i = 0; i < imax; ++i)
    {
      const CLTextGlyph * tmp = mvLabels[i];

      //find the corresponding SBML object
      std::map<const CLBase*, const SBase*>::const_iterator it = layoutmap.find(tmp);

      if (it != layoutmap.end() && it->second && dynamic_cast<const TextGlyph*>(it->second))
        {
          tmp->exportReferenceToSBML(const_cast<TextGlyph*>(dynamic_cast<const TextGlyph*>(it->second)), layoutmap);
        }
    }
}
Exemplo n.º 7
0
/**
 * This function produces a random layout. It first shufles around
 * metab glyphs and reaction centers, and finally corrects all ars
 */
void CCopasiSpringLayout::randomize()
{
  CRandom* pRandom = CRandom::createGenerator(CRandom::mt19937, CRandom::getSystemSeed());

  size_t i;

  //compartment glyphs

  //metab glyphs
  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
    {
      CLMetabGlyph* pMetabGlyph = &mpLayout->getListOfMetaboliteGlyphs()[i];
      const CMetab* pMetab = dynamic_cast<const CMetab*>(pMetabGlyph->getModelObject());

      if (!pMetab)
        continue;

      //find the compartment glyph
      const CCompartment* pComp = pMetab->getCompartment();

      if (!pComp)
        continue;

      const CLCompartmentGlyph* pCompGlyph = NULL;
      size_t j;

      for (j = 0; j < mpLayout->getListOfCompartmentGlyphs().size(); ++j)
        if (mpLayout->getListOfCompartmentGlyphs()[j].getModelObjectKey()
            == pComp->getKey())
          {
            pCompGlyph = &mpLayout->getListOfCompartmentGlyphs()[j];
            break;
          }

      if (pCompGlyph)
        randomlyPlaceGlyphInCompartmentGlyph(pMetabGlyph, pCompGlyph, pRandom);
      else
        randomlyPlaceGlyphInDimensions(pMetabGlyph, &mpLayout->getDimensions(), pRandom);
    }

  //reaction glyphs
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
    {
      CLReactionGlyph* pReactionGlyph = &mpLayout->getListOfReactionGlyphs()[i];
      CLPoint center(0, 0);
      size_t count;

      for (count = 0; count < pReactionGlyph->getListOfMetabReferenceGlyphs().size(); ++count)
        {
          CLMetabGlyph* metabGlyph = pReactionGlyph->getListOfMetabReferenceGlyphs()[count].getMetabGlyph();

          if (metabGlyph == NULL) continue;

          center = center + metabGlyph->getBoundingBox().getCenter();
        }

      center = center * (1.0 / pReactionGlyph->getListOfMetabReferenceGlyphs().size());
      center = center + CLPoint(pRandom->getRandomCC() * 20 - 10,  pRandom->getRandomCC() * 20 - 10);

      pReactionGlyph->setPosition(center);

      /*if (pCompGlyph)
        randomlyPlaceGlyphInCompartmentGlyph(pMetabGlyph, pCompGlyph);
      else
        randomlyPlaceGlyphInDimensions(pMetabGlyph, &mpCurrentLayout->getDimensions());*/
    }

  placeTextGlyphs(mpLayout);
  delete pRandom;

  finalizeState();
}
Exemplo n.º 8
0
double CCopasiSpringLayout::getPotential()
{
  //here we need to add the different effects that contribute to the potential

  double tmp = 0;

  //repulsion between species nodes
  unsigned int i, j;

  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size() - 1; ++i)
    for (j = i + 1; j < mpLayout->getListOfMetaboliteGlyphs().size(); ++j)
      {
        if (i != j)
          tmp += mpPar->values[0] * potSpeciesSpecies(mpLayout->getListOfMetaboliteGlyphs()[i], mpLayout->getListOfMetaboliteGlyphs()[j]);
      }

  // only if we have reactions!
  if (mpLayout->getListOfReactionGlyphs().size() > 0)
    {
      //repulsion between species nodes and reaction nodes
      for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
        for (j = 0; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
          {
            tmp += mpPar->values[0] * potSpeciesReaction(mpLayout->getListOfMetaboliteGlyphs()[i], mpLayout->getListOfReactionGlyphs()[j]);
          }

      //repulsion between reaction nodes
      for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() - 1; ++i)
        for (j = i + 1; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
          {
            if (i != j)
              tmp += mpPar->values[0] * potReactionReaction(mpLayout->getListOfReactionGlyphs()[i], mpLayout->getListOfReactionGlyphs()[j]);
          }
    }

  //spring force for species references
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
    {
      CLReactionGlyph* pRG = &mpLayout->getListOfReactionGlyphs()[i];

      for (j = 0; j < pRG->getListOfMetabReferenceGlyphs().size(); ++j)
        {
          tmp += potEdge(pRG->getListOfMetabReferenceGlyphs()[j], *pRG);

          //second order
          CLMetabReferenceGlyph::Role role = pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole();

          if (role != CLMetabReferenceGlyph::SUBSTRATE && role != CLMetabReferenceGlyph::SIDESUBSTRATE)
            continue;

          double dist = role == CLMetabReferenceGlyph::SUBSTRATE ? mpPar->values[1] : mpPar->values[3];
          size_t k;

          for (k = 0; k < pRG->getListOfMetabReferenceGlyphs().size(); ++k)
            {
              CLMetabReferenceGlyph::Role role2 = pRG->getListOfMetabReferenceGlyphs()[k].getFunctionalRole();

              if (role2 != CLMetabReferenceGlyph::PRODUCT && role2 != CLMetabReferenceGlyph::SIDEPRODUCT)
                continue;

              dist += role2 == CLMetabReferenceGlyph::PRODUCT ? mpPar->values[1] : mpPar->values[3];

              tmp += mpPar->values[5] * potSecondOrderEdge(pRG->getListOfMetabReferenceGlyphs()[j], pRG->getListOfMetabReferenceGlyphs()[k], dist);
            }
        }
    }

  for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size(); ++i)
    {
      CLGeneralGlyph* pRG = &mpLayout->getListOfGeneralGlyphs()[i];

      for (j = 0; j < pRG->getListOfReferenceGlyphs().size(); ++j)
        {
          tmp += potGeneralEdge(pRG->getListOfReferenceGlyphs()[j], *pRG);
        }
    }

  /*
      //forces at reaction nodes
      for (i=0; i<mReactionNodes.size(); ++i)
        {
          tmp += 3000* potReaction(mReactionNodes[i]);
        }
  */

  //force to keep species in compartment
  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
    {
      CLMetabGlyph* tmpMG = &mpLayout->getListOfMetaboliteGlyphs()[i];
      std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpMG);

      if (mapIt == mCompartmentMap.end())
        {
          //there is no information in the map. Should not happen.
#ifdef COPASI_DEBUG
          std::cout << "No compartment info for a species glyph!!!" << std::endl;
#endif
          continue;
        }

      CLCompartmentGlyph* tmpCG = mapIt->second;

      if (tmpCG) //the species glyph is inside a compartment glyph
        tmp +=  mpPar->values[6] * potSpeciesCompartment(*tmpMG, *tmpCG);
    }

  //force to keep reaction nodes in compartment
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
    {
      CLReactionGlyph* tmpRG = &mpLayout->getListOfReactionGlyphs()[i];
      std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpRG);

      if (mapIt == mCompartmentMap.end())
        {
          //there is no information in the map. Should not happen.
#ifdef COPASI_DEBUG
          std::cout << "No compartment info for a reaction glyph!!!" << std::endl;
#endif
          continue;
        }

      CLCompartmentGlyph* tmpCG = mapIt->second;

      if (tmpCG) //the reaction glyph is inside a compartment glyph
        tmp += mpPar->values[7] * potReactionCompartment(*tmpRG, *tmpCG);
    }

  /*

    //force to shrink compartments
    for (i=0; i<mCompartmentNodes.size(); ++i)
      {
        tmp += 0.2*(fabs(mCompartmentNodes[i].w-100)+fabs(mCompartmentNodes[i].h-100));
      }

    //repulsion between compartments
    for (i=0; i<mCompartmentNodes.size(); ++i)
    for (j=0; j<mCompartmentNodes.size(); ++j)
      {
        if (i!=j)
          tmp += 100*potCompartmentCompartment(mCompartmentNodes[i], mCompartmentNodes[j]);
      }

    //centering force
    for (i=0; i<mCompartmentNodes.size(); ++i)
      {
        tmp += 10*(fabs(mCompartmentNodes[i].x)+fabs(mCompartmentNodes[i].y));
      }
    */
  return tmp;
}
Exemplo n.º 9
0
void CCopasiSpringLayout::finalizeState()
{
  unsigned int i;

  //update the positions of the dependent glyphs
  //this can be done here since we assume that those glyphs
  //do not affect the layout.
  updateFixedRelations();

  //for now, only create curves for the reaction glyphs
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
    {
      CLReactionGlyph* pRG = &mpLayout->getListOfReactionGlyphs()[i];

      //Determine the average position of substrates and products, giving less weight to side reactants
      CLPoint s, p;
      double s_c = 0; double p_c = 0;
      unsigned int j, jmax = pRG->getListOfMetabReferenceGlyphs().size();

      for (j = 0; j < jmax; ++j)
        {
          if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::SUBSTRATE)
            {
              CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph();

              if (metabGlyph != NULL)
                {
                  s_c += 1.0;
                  s = s + metabGlyph->getBoundingBox().getCenter();
                }
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::SIDESUBSTRATE)
            {
              CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph();

              if (metabGlyph != NULL)
                {
                  s_c += 0.1;
                  s = s + metabGlyph->getBoundingBox().getCenter() * 0.1;
                }
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::PRODUCT)
            {
              CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph();

              if (metabGlyph != NULL)
                {
                  p_c += 1.0;
                  p = p + metabGlyph->getBoundingBox().getCenter();
                }
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::SIDEPRODUCT)
            {
              CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph();

              if (metabGlyph != NULL)
                {

                  p_c += 0.1;
                  p = p + metabGlyph->getBoundingBox().getCenter() * 0.1;
                }
            }
        }

      CLPoint position = pRG->getPosition();

      if (position.getX() == 0 && position.getY() == 0
          && pRG->getDimensions().getWidth() == 0
          && pRG->getDimensions().getHeight() == 0
          && pRG->getCurve().getNumCurveSegments() > 0)
        {
          position = pRG->getCurve().getCurveSegments()[0].getStart();
          pRG->setPosition(position);
        }

      if (s_c > 0)
        s = s * (1 / s_c);
      else
        {
          s = position;
        }

      if (p_c > 0)
        p = p * (1 / p_c);
      else
        p = position;

      CLPoint dir = p - s; //overall direction of reaction

      if (dir.getX() == 0 && dir.getY() == 0)
        dir = CLPoint(1, 0);

      CLPoint ortho_dir = CLPoint(dir.getY(), -dir.getX());
      ortho_dir.scale(1 / sqrt(pow(ortho_dir.getX(), 2) + pow(ortho_dir.getY(), 2)));

      CLPoint reaction_s = position - (dir * 0.05);
      CLPoint reaction_p = position + (dir * 0.05);
      CLPoint reaction_m1 = position + ortho_dir * 10;
      CLPoint reaction_m2 = position - ortho_dir * 10;

      pRG->getCurve().clear();
      pRG->getCurve().addCurveSegment(CLLineSegment(reaction_s, reaction_p));

      for (j = 0; j < jmax; ++j)
        {
          //here we need to generate the curves for the MetabReferenceGlyphs.
          //we will need to consider the size of the glyphs, role of the metab in the reaction, etc.
          //For now, only a primitive implementation: TODO: improve
          CLMetabReferenceGlyph* pMRG = &pRG->getListOfMetabReferenceGlyphs()[j];
          double direction;
          //double modifierLength = -0.2;

          switch (pMRG->getFunctionalRole())
            {
              case CLMetabReferenceGlyph::SUBSTRATE :
              case CLMetabReferenceGlyph::SIDESUBSTRATE :
              {
                direction = -0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_s + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_s,
                                                 metabPoint,
                                                 reaction_s + dir * direction,
                                                 (reaction_s + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              case CLMetabReferenceGlyph::PRODUCT :
              case CLMetabReferenceGlyph::SIDEPRODUCT :
              {
                direction = 0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_p + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_p,
                                                 metabPoint,
                                                 reaction_p + dir * direction,
                                                 (reaction_p + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              default:
              {
                CLPoint reactionPoint;

                if (pMRG->getMetabGlyph() && ortho_dir.dot(pRG->getPosition() - pMRG->getMetabGlyph()->getPosition()) < 0)
                  {
                    direction = +10.0;
                    reactionPoint = reaction_m1;
                  }
                else
                  {
                    direction = -10.0;
                    reactionPoint = reaction_m2;
                  }

                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reactionPoint + dir * 0 * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(metabPoint,
                                                 reactionPoint,
                                                 (reactionPoint + dir * (0 * direction * 1.5) + metabPoint) * 0.5,
                                                 reactionPoint + ortho_dir * direction));
              }
            }
        }
    }

  //update the curves in the general glyph
  for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size() ; ++i)
    {
      CLGeneralGlyph* pGG = &mpLayout->getListOfGeneralGlyphs()[i];

      size_t j;

      for (j = 0; j < pGG->getListOfReferenceGlyphs().size(); ++j)
        {
          CLReferenceGlyph* pRG = &pGG->getListOfReferenceGlyphs()[j];

          if (pRG->getCurve().getNumCurveSegments() == 0) continue;

          CLPoint refPoint = borderProjection(pRG->getTargetGlyph(), pRG->getBoundingBox().getCenter(), 5);
          pRG->getCurve().clear();
          pRG->getCurve().addCurveSegment(CLLineSegment(refPoint, pRG->getBoundingBox().getCenter()));
        }
    }

  //calculate bounding box for the layout, or recenter the layout
  mpLayout->calculateAndAssignBounds();
}
Exemplo n.º 10
0
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;
}