COPASI API  4.16.103
Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | List of all members
CSBMLExporter Class Reference

#include <CSBMLExporter.h>

Collaboration diagram for CSBMLExporter:
Collaboration graph
[legend]

Public Member Functions

 CSBMLExporter ()
 
void disownSBMLDocument ()
 
bool exportModel (CCopasiDataModel &dataModel, const std::string &filename, unsigned int sbmlLevel=2, unsigned int sbmlVersion=1, bool overwrite=false)
 
const std::string exportModelToString (CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion)
 
const std::map< const
CCopasiObject *, SBase * > & 
getCOPASI2SBMLMap () const
 
SBMLDocument * getSBMLDocument ()
 
bool isSetExportCOPASIMIRIAM () const
 
void setExportCOPASIMIRIAM (bool exportMIRIAM)
 
 ~CSBMLExporter ()
 

Static Public Member Functions

static const std::string createUniqueId (const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
 
static const std::vector
< SBMLIncompatibility
isModelSBMLCompatible (const CCopasiDataModel &pDataModel, int sbmlLevel, int sbmlVersion)
 

Protected Member Functions

void assignSBMLIdsToReactions (CModel *pModel)
 
void checkForUnsupportedFunctionCalls (const CCopasiDataModel &dataModel, unsigned int sbmlLEvel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
 
void checkForUnsupportedObjectReferences (const CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
 
void collectIds (const CCopasiDataModel &dataModel, std::map< std::string, const SBase * > &idMap)
 
ASTNode * convertToASTNode (const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
 
void convertToLevel1 ()
 
void createAreaUnit (const CCopasiDataModel &dataModel)
 
void createCompartment (CCompartment &compartment)
 
void createCompartments (CCopasiDataModel &dataModel)
 
void createEvent (CEvent &event, Event *pSBMLEvent, CCopasiDataModel &dataModel)
 
void createEvents (CCopasiDataModel &dataModel)
 
void createFunctionDefinition (CFunction &function, CCopasiDataModel &dataModel)
 
void createFunctionDefinitions (CCopasiDataModel &dataModel)
 
const std::map< std::string,
const SBase * > 
createIdMap (const Model &sbmlModel)
 
void createInitialAssignment (const CModelEntity &modelEntity, CCopasiDataModel &dataModel)
 
void createInitialAssignments (CCopasiDataModel &dataModel)
 
CEvaluationNodecreateKineticExpression (CFunction *pFun, const std::vector< std::vector< std::string > > &arguments)
 
KineticLaw * createKineticLaw (CReaction &reaction, CCopasiDataModel &dataModel, unsigned int level, unsigned int version)
 
void createLengthUnit (const CCopasiDataModel &dataModel)
 
void createMetabolite (CMetab &metab)
 
void createMetabolites (CCopasiDataModel &dataModel)
 
void createParameter (CModelValue &parameter)
 
void createParameters (CCopasiDataModel &dataModel)
 
void createReaction (CReaction &reaction, CCopasiDataModel &dataModel)
 
void createReactions (CCopasiDataModel &dataModel)
 
void createRule (const CModelEntity &modelEntity, CCopasiDataModel &dataModel, Rule *pOldRule)
 
void createRules (CCopasiDataModel &dataModel)
 
void createSBMLDocument (CCopasiDataModel &dataModel)
 
void createSubstanceUnit (const CCopasiDataModel &dataModel)
 
void createTimeUnit (const CCopasiDataModel &dataModel)
 
void createUnits (const CCopasiDataModel &dataModel)
 
void createVolumeUnit (const CCopasiDataModel &dataModel)
 
void exportEventAssignments (const CEvent &event, Event *pSBMLEvent, CCopasiDataModel &dataModel)
 
void findAvogadro (const CCopasiDataModel &dataModel)
 
bool hasVolumeAssignment (const CCopasiDataModel &dataModel)
 
std::vector< CModelEntity * > orderRules (const CCopasiDataModel &dataModel)
 
void outputIncompatibilities () const
 
void removeInitialAssignment (const std::string &sbmlId)
 
void removeRule (const std::string &sbmlId)
 
void removeUnusedObjects ()
 
void replace_local_parameters (ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
 
XMLNode * replaceChild (const XMLNode *pParent, const XMLNode *pNewChild, unsigned int index)
 
CEvaluationNodereplaceSpeciesReferences (const CEvaluationNode *pOrigNode, const CCopasiDataModel &dataModel)
 
void restore_local_parameters (ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
 
void setFunctionSBMLIds (const CEvaluationNode *pNode, CCopasiDataModel &dataModel)
 
void updateCOPASI2SBMLMap (const CCopasiDataModel &dataModel)
 
bool updateMIRIAMAnnotation (const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
 

Static Protected Member Functions

static void check_for_spatial_size_units (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void checkForEvents (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void checkForInitialAssignments (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void checkForODESpeciesInNonfixedCompartment (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > result)
 
static void checkForPiecewiseFunctions (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void checkForPiecewiseFunctions (const CEvaluationNode &node, std::vector< SBMLIncompatibility > &result, const std::string &objectName, const std::string &objectType)
 
static void checkForUnsupportedFunctionCalls (const CEvaluationNode &node, const std::set< CEvaluationNodeFunction::SubType > &unsupportedFunctions, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription)
 
static void checkForUnsupportedObjectReferences (const CEvaluationTree &expression, const CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result, bool initialExpression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
 
static void convert_to_l1v1 (std::string &l1v2_string)
 
static ASTNode * convertASTTreeToLevel1 (const ASTNode *pNode, const ListOfFunctionDefinitions &functions, std::string &message)
 
static const std::set
< CFunction * > 
createFunctionSetFromFunctionNames (const std::set< std::string > &names, CFunctionDB *pFunDB)
 
static CEvaluationNodecreateMassActionExpression (const std::vector< std::vector< std::string > > &arguments, bool isReversible)
 
static ASTNode * createTimesTree (const CCopasiVector< CChemEqElement > &vect, unsigned int pos=0)
 
static const std::set
< CEvaluationNodeFunction::SubType
createUnsupportedFunctionTypeSet (unsigned int sbmlLevel)
 
static void findDirectlyUsedFunctions (const CEvaluationNode *pRootNode, std::set< std::string > &result)
 
static void findModelEntityDependencies (const CEvaluationNode *pNode, const CCopasiDataModel &dataModel, std::set< const CModelEntity * > &dependencies)
 
static const std::vector
< CFunction * > 
findUsedFunctions (std::set< CFunction * > &functions, CFunctionDB *pFunctionDB)
 
static ASTNode * isDividedByVolume (const ASTNode *pRootNode, const std::string &compartmentId)
 
static void isEventAssignmentSBMLCompatible (std::string &key, const CExpression *pExpression, const CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion, const std::string &eventName, std::vector< SBMLIncompatibility > &result)
 
static void isEventSBMLCompatible (const CEvent *pEvent, const CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
 
static void isExpressionSBMLCompatible (const CEvaluationTree &expr, const CCopasiDataModel &dataModel, int sbmlLevel, int sbmlVersion, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription, bool initialExression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
 
static void isExpressionSBMLL1Compatible (const CEvaluationTree &expr, const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void isExpressionSBMLL2V1Compatible (const CEvaluationTree &expr, const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void isExpressionSBMLL2V3Compatible (const CEvaluationTree &expression, const CCopasiDataModel &pDataModel, std::vector< SBMLIncompatibility > &result)
 
static void isModelSBMLL1Compatible (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void isModelSBMLL2V1Compatible (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static void isModelSBMLL2V3Compatible (const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
 
static bool isValidSId (const std::string &id)
 
static CEvaluationNodemultiplyByObject (const CEvaluationNode *pOrigNode, const CCopasiObject *pObject)
 
static ASTNode * replaceL1IncompatibleNodes (const ASTNode *pNode)
 
static bool setSBMLNotes (SBase *pSBase, const CAnnotation *pAnno)
 

Protected Attributes

std::vector< CModelEntity * > mAssignmentVector
 
bool mAvogadroCreated
 
std::map< const CCopasiObject
*, SBase * > 
mCOPASI2SBMLMap
 
bool mDocumentDisowned
 
bool mExportCOPASIMIRIAM
 
ListOfFunctionDefinitions mExportedFunctions
 
std::map< std::string, const
CEvaluationTree * > 
mFunctionIdMap
 
std::map< const
FunctionDefinition *, const
CCopasiObject * > 
mFunctionMap
 
std::set< SBase * > mHandledSBMLObjects
 
bool mHaveModelHistoryAuthorWarning
 
bool mHaveModelHistoryCreationDateWarning
 
bool mHaveModelHistoryModificationDateWarning
 
std::map< std::string, const
SBase * > 
mIdMap
 
std::vector< SBMLIncompatibilitymIncompatibilities
 
bool mIncompleteExport
 
std::vector< CModelEntity * > mInitialAssignmentVector
 
std::map< const std::string,
Parameter * > 
mInitialValueMap
 
std::map< std::string, const
SBase * > 
mMetaIdMap
 
bool mMIRIAMWarning
 
std::vector< CModelEntity * > mODEVector
 
std::map< std::string,
Parameter * > 
mParameterReplacementMap
 
const CModelValuempAvogadro
 
SBMLDocument * mpSBMLDocument
 
unsigned int mSBMLLevel
 
unsigned int mSBMLVersion
 
std::set< std::string > mSpatialSizeUnitsSpecies
 
std::set< CFunction * > mUsedFunctions
 
bool mVariableVolumes
 

Detailed Description

Definition at line 52 of file CSBMLExporter.h.

Constructor & Destructor Documentation

CSBMLExporter::CSBMLExporter ( )

Default Konstruktor

Definition at line 328 of file CSBMLExporter.cpp.

329 {}
bool mExportCOPASIMIRIAM
Definition: CSBMLExporter.h:74
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
ListOfFunctionDefinitions mExportedFunctions
Definition: CSBMLExporter.h:77
bool mDocumentDisowned
Definition: CSBMLExporter.h:73
bool mIncompleteExport
Definition: CSBMLExporter.h:66
bool mAvogadroCreated
Definition: CSBMLExporter.h:69
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
const CModelValue * mpAvogadro
Definition: CSBMLExporter.h:68
bool mVariableVolumes
Definition: CSBMLExporter.h:67
CSBMLExporter::~CSBMLExporter ( )

Destruktor

Definition at line 331 of file CSBMLExporter.cpp.

References mDocumentDisowned, mpSBMLDocument, and pdelete.

332 {
333  if (this->mDocumentDisowned == false)
334  {
336  }
337 };
#define pdelete(p)
Definition: copasi.h:215
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
bool mDocumentDisowned
Definition: CSBMLExporter.h:73

Member Function Documentation

void CSBMLExporter::assignSBMLIdsToReactions ( CModel pModel)
protected

Since we want to replace local reaction parameters by global parameters if they are used in an assignment, we have to create the reactions after creating the rules and events. On the other hand, a reaction flux might also be referenced in an assignment or an event and the creation of this rule or event only works if the reactions already have SBML ids. To solve this problem, the reactions have to be assigned SBML ids prior to creating rules and events. This is what this method does.

Definition at line 7556 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), createUniqueId(), CCopasiVector< T >::end(), CModel::getReactions(), and mIdMap.

Referenced by createSBMLDocument().

7557 {
7558  std::string sbmlId;
7559  CCopasiVectorNS<CReaction>::const_iterator it = pModel->getReactions().begin(), endit = pModel->getReactions().end();
7560 
7561  while (it != endit)
7562  {
7563  if ((*it)->getSBMLId().empty())
7564  {
7565  sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, (*it)->getObjectName(), false);
7566  (*it)->setSBMLId(sbmlId);
7567  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, (const SBase*)NULL));
7568  }
7569 
7570  ++it;
7571  }
7572 }
iterator begin()
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
iterator end()
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
void CSBMLExporter::check_for_spatial_size_units ( const CCopasiDataModel dataModel,
std::vector< SBMLIncompatibility > &  result 
)
staticprotected

Go through all species in the model and check if the corresponding species in the SBML model has the spatialSizeUnits attribute set. This attribute is not supported in SBML L2V3 and above, so we have to get rid of this attribute when we export to a level equal to or higher than L2V3. If the attribute has the same value as the compartments units, we can just delete it without changing the model, otherwise we have to give a corresponding warning.

Definition at line 2597 of file CSBMLExporter.cpp.

References SBMLImporter::areSBMLUnitDefinitionsIdentical(), CCopasiVector< T >::begin(), CCopasiVector< T >::end(), CCopasiMessage::EXCEPTION, CModel::getMetabolites(), CCopasiDataModel::getModel(), SBMLImporter::getSBMLUnitDefinitionForId(), and MCSBML.

Referenced by createMetabolites(), and isModelSBMLL2V3Compatible().

2598 {
2599  const SBMLDocument* pSBMLDocument = const_cast<const SBMLDocument*>(const_cast<CCopasiDataModel&>(dataModel).getCurrentSBMLDocument());
2600 
2601  if (pSBMLDocument != NULL)
2602  {
2603  // check all species in the model if they have a spatial size attribute set
2604  // and if it is identical to the unit of the compartment the species is in
2605  const CModel* pModel = dataModel.getModel();
2606 
2607  if (pModel != NULL)
2608  {
2609  CCopasiVector<CMetab>::const_iterator it = pModel->getMetabolites().begin(), endit = pModel->getMetabolites().end();
2610  std::set<std::string> badSpecies;
2611  const std::map<CCopasiObject*, SBase*>& copasi2sbmlmap = const_cast<CCopasiDataModel&>(dataModel).getCopasi2SBMLMap();
2612  std::map<CCopasiObject*, SBase*>::const_iterator pos;
2613  const Species* pSBMLSpecies = NULL;
2614  std::string spatialSizeUnits;
2615 
2616  while (it != endit)
2617  {
2618  pos = copasi2sbmlmap.find(*it);
2619 
2620  if (pos != copasi2sbmlmap.end())
2621  {
2622  // check for the spatial size units attribute
2623  pSBMLSpecies = dynamic_cast<const Species*>(pos->second);
2624  assert(pSBMLSpecies != NULL);
2625 
2626  if (pSBMLSpecies == NULL) continue;
2627 
2628  if (pSBMLSpecies->isSetSpatialSizeUnits())
2629  {
2630  spatialSizeUnits = pSBMLSpecies->getSpatialSizeUnits();
2631  // check if the units are the same as the one on the species
2632  // compartment
2633  assert(pSBMLDocument->getModel() != NULL);
2634  const Compartment* pCompartment = pSBMLDocument->getModel()->getCompartment(pSBMLSpecies->getCompartment());
2635  assert(pCompartment != NULL);
2636 
2637  if (pCompartment != NULL)
2638  {
2639  UnitDefinition* pUDef1 = NULL;
2640  UnitDefinition* pUDef2 = NULL;
2641 
2642  if (pCompartment->isSetUnits())
2643  {
2644  assert(pSBMLDocument->getModel() != NULL);
2645 
2646  if (pSBMLDocument->getModel() != NULL)
2647  {
2648  pUDef1 = SBMLImporter::getSBMLUnitDefinitionForId(pCompartment->getUnits(), pSBMLDocument->getModel());
2649  }
2650  }
2651  else
2652  {
2653  // the compartment has the default units associated with the
2654  // symbol length , area or volume depending on the spatial size
2655  // of the compartment
2656  assert(pSBMLDocument->getModel() != NULL);
2657 
2658  if (pSBMLDocument->getModel() != NULL)
2659  {
2660  switch (pCompartment->getSpatialDimensions())
2661  {
2662  case 0:
2663  // the species is not allowed to have a
2664  // spatialDimensionsUnit attribute
2665  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 83 , pSBMLSpecies->getId().c_str());
2666  break;
2667 
2668  case 1:
2669  pUDef1 = SBMLImporter::getSBMLUnitDefinitionForId("length", pSBMLDocument->getModel());
2670  break;
2671 
2672  case 2:
2673  pUDef1 = SBMLImporter::getSBMLUnitDefinitionForId("area", pSBMLDocument->getModel());
2674  break;
2675 
2676  case 3:
2677  pUDef1 = SBMLImporter::getSBMLUnitDefinitionForId("volume", pSBMLDocument->getModel());
2678  break;
2679 
2680  default:
2681  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 82 , pCompartment->getId().c_str());
2682  break;
2683  }
2684  }
2685  }
2686 
2687  if (pUDef1 != NULL && pUDef2 != NULL)
2688  {
2689  // compare the two unit definitions
2690  if (!SBMLImporter::areSBMLUnitDefinitionsIdentical(pUDef1, pUDef2))
2691  {
2692  // add the species to bad species
2693  badSpecies.insert(pSBMLSpecies->getId());
2694  }
2695  }
2696 
2697  // delete the unit definitions
2698  if (pUDef1 != NULL)
2699  {
2700  delete pUDef1;
2701  }
2702 
2703  if (pUDef2 != NULL)
2704  {
2705  delete pUDef2;
2706  }
2707  }
2708  }
2709  }
2710 
2711  ++it;
2712  }
2713 
2714  if (!badSpecies.empty())
2715  {
2716  // create the incompatibility message
2717  std::ostringstream os;
2718  std::set<std::string>::const_iterator sit = badSpecies.begin(), sendit = badSpecies.end();
2719 
2720  while (sit != sendit)
2721  {
2722  os << *sit << ", ";
2723  ++sit;
2724  }
2725 
2726  result.push_back(SBMLIncompatibility(2, os.str().substr(0, os.str().size() - 2).c_str()));
2727  }
2728  }
2729  }
2730 }
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
iterator begin()
#define MCSBML
iterator end()
static UnitDefinition * getSBMLUnitDefinitionForId(const std::string &unitId, const Model *pSBMLModel)
Definition: CModel.h:50
static bool areSBMLUnitDefinitionsIdentical(const UnitDefinition *pUdef1, const UnitDefinition *pUdef2)
void CSBMLExporter::checkForEvents ( const CCopasiDataModel dataModel,
std::vector< SBMLIncompatibility > &  result 
)
staticprotected

Checks if the given datamodel contains events. This is called if SBML Level 1 is to be exported.

Definition at line 4552 of file CSBMLExporter.cpp.

References CModel::getEvents(), CCopasiDataModel::getModel(), and CCopasiVector< T >::size().

Referenced by createEvents(), and isModelSBMLL1Compatible().

4553 {
4554  if (dataModel.getModel() != NULL && dataModel.getModel()->getEvents().size() > 0)
4555  {
4556  result.push_back(SBMLIncompatibility(7));
4557  }
4558 }
CCopasiVectorN< CEvent > & getEvents()
Definition: CModel.cpp:1110
virtual size_t size() const
void CSBMLExporter::checkForInitialAssignments ( const CCopasiDataModel dataModel,
std::vector< SBMLIncompatibility > &  result 
)
staticprotected

This method checks wether the given model contains any initial assignments.

This method checks whether the given model contains any initial assignments.

Definition at line 2887 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), CCopasiVector< T >::end(), CModel::getCompartments(), CModel::getMetabolites(), CCopasiDataModel::getModel(), and CModel::getModelValues().

Referenced by createSBMLDocument(), isModelSBMLL1Compatible(), and isModelSBMLL2V1Compatible().

2888 {
2889  const CModel* pModel = dataModel.getModel();
2890 
2891  if (pModel != NULL)
2892  {
2893  // check for rules
2894  const CCopasiVectorNS<CCompartment>& compartments = pModel->getCompartments();
2895  CCopasiVectorNS<CCompartment>::const_iterator compIt = compartments.begin(), compEndit = compartments.end();
2896 
2897  while (compIt != compEndit)
2898  {
2899  if ((*compIt)->getInitialExpression() != "")
2900  {
2901  result.push_back(SBMLIncompatibility(5, "Compartment", (*compIt)->getObjectName().c_str()));
2902  }
2903 
2904  ++compIt;
2905  }
2906 
2907  const CCopasiVector<CMetab>& metabs = pModel->getMetabolites();
2908 
2909  CCopasiVector<CMetab>::const_iterator metabIt = metabs.begin(), metabEndit = metabs.end();
2910 
2911  while (metabIt != metabEndit)
2912  {
2913  if ((*metabIt)->getInitialExpression() != "")
2914  {
2915  result.push_back(SBMLIncompatibility(5, "Metabolite", (*metabIt)->getObjectName().c_str()));
2916  }
2917 
2918  ++metabIt;
2919  }
2920 
2921  const CCopasiVectorN<CModelValue>& parameters = pModel->getModelValues();
2922 
2923  CCopasiVectorN<CModelValue>::const_iterator mvIt = parameters.begin(), mvEndit = parameters.end();
2924 
2925  while (mvIt != mvEndit)
2926  {
2927  if ((*mvIt)->getInitialExpression() != "")
2928  {
2929  result.push_back(SBMLIncompatibility(5, "Parameter", (*mvIt)->getObjectName().c_str()));
2930  }
2931 
2932  ++mvIt;
2933  }
2934  }
2935 }
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
const CCopasiVectorN< CModelValue > & getModelValues() const
Definition: CModel.cpp:1060
iterator begin()
iterator end()
CCopasiVectorNS< CCompartment > & getCompartments()
Definition: CModel.cpp:1145
Definition: CModel.h:50
void CSBMLExporter::checkForODESpeciesInNonfixedCompartment ( const CCopasiDataModel dataModel,
std::vector< SBMLIncompatibility result 
)
staticprotected

Checks wether the model contains a metabolite that is defined by an ODE expression and that is located in a variable volume. Since COPASI interprets the expression differntly from SBML, we can not correctly export this yet. See Bug 903.

Checks whether the model contains a metabolite that is defined by an ODE expression and that is located in a variable volume. Since COPASI interprets the expression differently from SBML, we can not correctly export this yet. See Bug 903.

Definition at line 2738 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), CCopasiVector< T >::end(), CModelEntity::FIXED, CModel::getMetabolites(), CCopasiDataModel::getModel(), CCopasiObject::getObjectName(), CModelEntity::getStatus(), and CModelEntity::ODE.

Referenced by isModelSBMLCompatible().

2739 {
2740  const CModel* pModel = dataModel.getModel();
2741  const CCopasiVector<CMetab>& metabolites = pModel->getMetabolites();
2742  CCopasiVector<CMetab>::const_iterator it = metabolites.begin(), endit = metabolites.end();
2743 
2744  while (it != endit)
2745  {
2746  if ((*it)->getStatus() == CModelValue::ODE)
2747  {
2748  const CCompartment* pCompartment = (*it)->getCompartment();
2749  assert(pCompartment != NULL);
2750 
2751  if (pCompartment->getStatus() != CModelValue::FIXED)
2752  {
2753  result.push_back(SBMLIncompatibility(3, (*it)->getObjectName().c_str(), pCompartment->getObjectName().c_str()));
2754  }
2755  }
2756 
2757  ++it;
2758  }
2759 }
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
const std::string & getObjectName() const
iterator begin()
iterator end()
Definition: CModel.h:50
const CModelEntity::Status & getStatus() const
void CSBMLExporter::checkForPiecewiseFunctions ( const CCopasiDataModel dataModel,
std::vector< SBMLIncompatibility > &  result 
)
staticprotected

Checks all expressions in the given datamodel for piecewise defined functions.

Definition at line 5531 of file CSBMLExporter.cpp.

References CModelEntity::ASSIGNMENT, createFunctionSetFromFunctionNames(), findDirectlyUsedFunctions(), findUsedFunctions(), CModel::getCompartments(), CModelEntity::getExpressionPtr(), CReaction::getFunction(), CCopasiRootContainer::getFunctionList(), CModel::getMetabolites(), CCopasiDataModel::getModel(), CModel::getModelValues(), CCopasiObject::getObjectName(), CModel::getReactions(), CEvaluationTree::getRoot(), CModelEntity::getStatus(), CModelEntity::ODE, and CCopasiVector< T >::size().

Referenced by checkForPiecewiseFunctions(), and isModelSBMLL1Compatible().

5532 {
5533  std::set<std::string> usedFunctionNames;
5534  const CModel* pModel = dataModel.getModel();
5535 
5536  if (pModel == NULL) return;
5537 
5538  // go through all model entities and check assignments
5539  // we don't have to check initial assignment since those can not be exported
5540  // anyway
5541  const CModelEntity* pME = NULL;
5542  const CCopasiVectorNS<CCompartment>& compartments = pModel->getCompartments();
5543  size_t i, iMax = compartments.size();
5544 
5545  for (i = 0; i < iMax; ++i)
5546  {
5547  pME = compartments[i];
5548 
5550  {
5551  const CEvaluationTree* pTree = pME->getExpressionPtr();
5552  CSBMLExporter::findDirectlyUsedFunctions(pTree->getRoot(), usedFunctionNames);
5553  CSBMLExporter::checkForPiecewiseFunctions(*pTree->getRoot(), result, pME->getObjectName(), "rule for compartment");
5554  }
5555  }
5556 
5557  const CCopasiVector<CMetab>& metabolites = pModel->getMetabolites();
5558 
5559  iMax = metabolites.size();
5560 
5561  for (i = 0; i < iMax; ++i)
5562  {
5563  pME = metabolites[i];
5564 
5566  {
5567  const CEvaluationTree* pTree = pME->getExpressionPtr();
5568  CSBMLExporter::findDirectlyUsedFunctions(pTree->getRoot(), usedFunctionNames);
5569  CSBMLExporter::checkForPiecewiseFunctions(*pTree->getRoot(), result, pME->getObjectName(), "rule for metabolite");
5570  }
5571  }
5572 
5573  const CCopasiVectorN<CModelValue>& modelvalues = pModel->getModelValues();
5574 
5575  iMax = modelvalues.size();
5576 
5577  for (i = 0; i < iMax; ++i)
5578  {
5579  pME = modelvalues[i];
5580 
5582  {
5583  const CEvaluationTree* pTree = pME->getExpressionPtr();
5584  CSBMLExporter::findDirectlyUsedFunctions(pTree->getRoot(), usedFunctionNames);
5585  CSBMLExporter::checkForPiecewiseFunctions(*pTree->getRoot(), result, pME->getObjectName(), "rule for global parameter");
5586  }
5587  }
5588 
5589  // go through all reactions and check the function called in the kinetic
5590  // laws.
5591  CReaction* pReaction = NULL;
5592  const CCopasiVectorNS<CReaction>& reactions = pModel->getReactions();
5593  iMax = reactions.size();
5594 
5595  for (i = 0; i < iMax; ++i)
5596  {
5597  pReaction = reactions[i];
5598 
5599  if (pReaction->getFunction() != NULL)
5600  {
5601  CSBMLExporter::findDirectlyUsedFunctions(pReaction->getFunction()->getRoot(), usedFunctionNames);
5602  }
5603  }
5604 
5605  // check indirectly called functions
5606  std::set<CFunction*> directlyUsedFunctions = CSBMLExporter::createFunctionSetFromFunctionNames(usedFunctionNames, CCopasiRootContainer::getFunctionList());
5607  std::vector<CFunction*> functions = CSBMLExporter::findUsedFunctions(directlyUsedFunctions, CCopasiRootContainer::getFunctionList());
5608  std::vector<CFunction*>::const_iterator it = functions.begin(), endit = functions.end();
5609 
5610  while (it != endit)
5611  {
5612  CSBMLExporter::checkForPiecewiseFunctions(*(*it)->getRoot(), result, (*it)->getObjectName(), "function");
5613  ++it;
5614  }
5615 }
const CExpression * getExpressionPtr() const
static const std::vector< CFunction * > findUsedFunctions(std::set< CFunction * > &functions, CFunctionDB *pFunctionDB)
static void findDirectlyUsedFunctions(const CEvaluationNode *pRootNode, std::set< std::string > &result)
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
const std::string & getObjectName() const
const CCopasiVectorN< CModelValue > & getModelValues() const
Definition: CModel.cpp:1060
virtual size_t size() const
const CFunction * getFunction() const
Definition: CReaction.cpp:252
static void checkForPiecewiseFunctions(const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
static CFunctionDB * getFunctionList()
CCopasiVectorNS< CCompartment > & getCompartments()
Definition: CModel.cpp:1145
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
static const std::set< CFunction * > createFunctionSetFromFunctionNames(const std::set< std::string > &names, CFunctionDB *pFunDB)
Definition: CModel.h:50
const CModelEntity::Status & getStatus() const
CEvaluationNode * getRoot()
void CSBMLExporter::checkForPiecewiseFunctions ( const CEvaluationNode node,
std::vector< SBMLIncompatibility > &  result,
const std::string &  objectName,
const std::string &  objectType 
)
staticprotected

Checks the given node and all it's children for the occurence of piecewise functions.

Definition at line 5617 of file CSBMLExporter.cpp.

References checkForPiecewiseFunctions(), CEvaluationNode::CHOICE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), and CEvaluationNode::type().

5618 {
5619 
5620  // no need to go through the children.
5621  // one incompatibility warning is enough
5623  {
5624  result.push_back(SBMLIncompatibility(8, objectType.c_str(), objectName.c_str()));
5625  }
5626  else
5627  {
5628  // store the old size
5629  // if one error has been found, we can stop looking at the other
5630  // children
5631  size_t size = result.size();
5632  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(node.getChild());
5633 
5634  while (pChild != NULL && result.size() == size)
5635  {
5636  CSBMLExporter::checkForPiecewiseFunctions(*pChild, result, objectName, objectType);
5637  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5638  }
5639  }
5640 }
objectType
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
static void checkForPiecewiseFunctions(const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
void CSBMLExporter::checkForUnsupportedFunctionCalls ( const CCopasiDataModel dataModel,
unsigned int  sbmlLevel,
unsigned int  sbmlVersion,
std::vector< SBMLIncompatibility > &  result 
)
protected

This static methods checks, wether the model uses any function calls that can not be expressed in SBML like the random distribution functions.

This static methods checks, whether the model uses any function calls that can not be expressed in SBML like the random distribution functions.

Definition at line 2786 of file CSBMLExporter.cpp.

References createUnsupportedFunctionTypeSet(), CModelEntity::getExpressionPtr(), CModelEntity::getInitialExpressionPtr(), CCopasiObject::getObjectName(), CCopasiObject::getObjectType(), CEvaluationTree::getRoot(), mAssignmentVector, mInitialAssignmentVector, mODEVector, and mUsedFunctions.

Referenced by checkForUnsupportedFunctionCalls(), and isExpressionSBMLCompatible().

2788 {
2789  // Fill the set of unsupported functions depending on the level and
2790  // version
2791  std::set<CEvaluationNodeFunction::SubType> unsupportedFunctionTypes = CSBMLExporter::createUnsupportedFunctionTypeSet(sbmlLevel);
2792  // check all metabolites,parameters and compartments
2793  // make sure the list of assignments and initial assignments is filled
2794  // before this function is called
2795  size_t i, iMax = mAssignmentVector.size();
2796  const CModelEntity* pME = NULL;
2797 
2798  for (i = 0; i < iMax; ++i)
2799  {
2800  pME = mAssignmentVector[i];
2801  assert(pME != NULL);
2802 
2803  if (pME != NULL)
2804  {
2805  checkForUnsupportedFunctionCalls(*pME->getExpressionPtr()->getRoot(), unsupportedFunctionTypes, result, std::string(pME->getObjectType() + " called \"" + pME->getObjectName() + "\""));
2806  }
2807  }
2808 
2809  // check ode rules
2810  iMax = mODEVector.size();
2811 
2812  for (i = 0; i < iMax; ++i)
2813  {
2814  pME = mODEVector[i];
2815  assert(pME != NULL);
2816 
2817  if (pME != NULL)
2818  {
2819  checkForUnsupportedFunctionCalls(*pME->getExpressionPtr()->getRoot(), unsupportedFunctionTypes, result, std::string(pME->getObjectType() + " called \"" + pME->getObjectName() + "\""));
2820  }
2821  }
2822 
2823  // check initial assignments
2824  iMax = mInitialAssignmentVector.size();
2825 
2826  for (i = 0; i < iMax; ++i)
2827  {
2828  pME = mInitialAssignmentVector[i];
2829  assert(pME != NULL);
2830 
2831  if (pME != NULL)
2832  {
2833  checkForUnsupportedFunctionCalls(*pME->getInitialExpressionPtr()->getRoot(), unsupportedFunctionTypes, result, std::string(pME->getObjectType() + " called \"" + pME->getObjectName() + "\""));
2834  }
2835  }
2836 
2837  // if we already have a list of used functions, we can go through this here
2838  // make sure the list of used function has been filled before this is
2839  // called
2840  iMax = mUsedFunctions.size();
2841  std::set<CFunction*>::iterator it = this->mUsedFunctions.begin(), endit = this->mUsedFunctions.end();
2842 
2843  while (it != endit)
2844  {
2845  assert(*it != NULL);
2846 
2847  if (*it != NULL)
2848  {
2849  checkForUnsupportedFunctionCalls(*(*it)->getRoot(), unsupportedFunctionTypes, result, std::string("function called \"" + (*it)->getObjectName() + "\""));
2850  }
2851 
2852  ++it;
2853  }
2854 }
const CExpression * getExpressionPtr() const
const std::string & getObjectName() const
const std::string & getObjectType() const
std::vector< CModelEntity * > mAssignmentVector
Definition: CSBMLExporter.h:58
void checkForUnsupportedFunctionCalls(const CCopasiDataModel &dataModel, unsigned int sbmlLEvel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
static const std::set< CEvaluationNodeFunction::SubType > createUnsupportedFunctionTypeSet(unsigned int sbmlLevel)
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
CEvaluationNode * getRoot()
const CExpression * getInitialExpressionPtr() const
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
void CSBMLExporter::checkForUnsupportedFunctionCalls ( const CEvaluationNode node,
const std::set< CEvaluationNodeFunction::SubType > &  unsupportedFunctions,
std::vector< SBMLIncompatibility > &  result,
const std::string &  objectDescription 
)
staticprotected

This static methods checks recursively, whether the given CEvaluationNode constains any function calls that can not be expressed in SBML like the random distribution functions.

Definition at line 2861 of file CSBMLExporter.cpp.

References checkForUnsupportedFunctionCalls(), CEvaluationNode::FUNCTION, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getData(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::subType(), and CEvaluationNode::type().

2864 {
2866  {
2868 
2869  if (unsupportedFunctions.find(subtype) != unsupportedFunctions.end())
2870  {
2871  result.push_back(SBMLIncompatibility(2, node.getData().c_str(), objectDescription.c_str()));
2872  }
2873  }
2874 
2875  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(node.getChild());
2876 
2877  while (pChild != NULL)
2878  {
2879  checkForUnsupportedFunctionCalls(*pChild, unsupportedFunctions, result, objectDescription);
2880  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
2881  }
2882 }
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
void checkForUnsupportedFunctionCalls(const CCopasiDataModel &dataModel, unsigned int sbmlLEvel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
static Type type(const Type &type)
static Type subType(const Type &type)
virtual const Data & getData() const
Definition: CCopasiNode.h:118
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
void CSBMLExporter::checkForUnsupportedObjectReferences ( const CCopasiDataModel dataModel,
unsigned int  sbmlLevel,
unsigned int  sbmlVersion,
std::vector< SBMLIncompatibility > &  result 
)
protected

Checks all assignments (initial and transient) for references to objects that can not be exported to SBML.

Definition at line 2284 of file CSBMLExporter.cpp.

References CModelEntity::getExpressionPtr(), CModelEntity::getInitialExpressionPtr(), CCopasiDataModel::getModel(), mAssignmentVector, mInitialAssignmentVector, mInitialValueMap, and mODEVector.

Referenced by isExpressionSBMLCompatible().

2285 {
2286  // check all metabolites,parameters and compartments
2287  const CModel* pModel = dataModel.getModel();
2288  assert(pModel);
2289 
2290  if (pModel == NULL) return;
2291 
2292  size_t i, iMax = this->mAssignmentVector.size();
2293  const CModelEntity* pME;
2294 
2295  for (i = 0; i < iMax; ++i)
2296  {
2297  pME = this->mAssignmentVector[i];
2298  assert(pME != NULL);
2299 
2300  if (pME != NULL)
2301  {
2302  checkForUnsupportedObjectReferences(*pME->getExpressionPtr(), dataModel, sbmlLevel, sbmlVersion, result, false, &mInitialValueMap);
2303  }
2304  }
2305 
2306  // check ode rules
2307  iMax = this->mODEVector.size();
2308 
2309  for (i = 0; i < iMax; ++i)
2310  {
2311  pME = this->mODEVector[i];
2312  assert(pME != NULL);
2313 
2314  if (pME != NULL)
2315  {
2316  checkForUnsupportedObjectReferences(*pME->getExpressionPtr(), dataModel, sbmlLevel, sbmlVersion, result, false, &mInitialValueMap);
2317  }
2318  }
2319 
2320  // check initial assignments
2321  iMax = this->mInitialAssignmentVector.size();
2322 
2323  for (i = 0; i < iMax; ++i)
2324  {
2325  pME = this->mInitialAssignmentVector[i];
2326  assert(pME != NULL);
2327 
2328  if (pME != NULL)
2329  {
2330  checkForUnsupportedObjectReferences(*pME->getInitialExpressionPtr(), dataModel, sbmlLevel, sbmlVersion, result, false, &mInitialValueMap);
2331  }
2332  }
2333 }
const CExpression * getExpressionPtr() const
std::vector< CModelEntity * > mAssignmentVector
Definition: CSBMLExporter.h:58
std::map< const std::string, Parameter * > mInitialValueMap
Definition: CSBMLExporter.h:79
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
Definition: CModel.h:50
void checkForUnsupportedObjectReferences(const CCopasiDataModel &dataModel, unsigned int sbmlLevel, unsigned int sbmlVersion, std::vector< SBMLIncompatibility > &result)
const CExpression * getInitialExpressionPtr() const
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
void CSBMLExporter::checkForUnsupportedObjectReferences ( const CEvaluationTree expression,
const CCopasiDataModel dataModel,
unsigned int  sbmlLevel,
unsigned int  sbmlVersion,
std::vector< SBMLIncompatibility > &  result,
bool  initialExpression = false,
std::map< const std::string, Parameter * > *  initialMap = NULL 
)
staticprotected

Checks the given expression for references to objects that can not be exported to SBML.

Definition at line 2376 of file CSBMLExporter.cpp.

References addToInitialValueMap(), CCopasiDataModel::getModel(), CEvaluationTree::getNodeList(), CEvaluationNodeObject::getObjectCN(), CCopasiObject::getObjectName(), CCopasiObject::getObjectParent(), CCopasiObject::getObjectType(), CCopasiObject::isReference(), CEvaluationNode::OBJECT, CCopasiDataModel::ObjectFromName(), and CEvaluationNode::type().

2384 {
2385  // SBML Level 1 and Level 2 Version 1 can have references to transient values of
2386  // compartments, metabolites and global parameters as well as time (model)
2387 
2388  // SBML Level 2 Version 2 and above can have the same references as level 1 plus references to
2389  // reaction fluxes.
2390 
2391  // Starting with COPASI Build 30 references to local parameters are allowed
2392  // as well because they are converted to global parameters
2393  const std::vector<CEvaluationNode*>& objectNodes = expr.getNodeList();
2394  size_t j, jMax = objectNodes.size();
2395 
2396  for (j = 0; j < jMax; ++j)
2397  {
2398  if (CEvaluationNode::type(objectNodes[j]->getType()) == CEvaluationNode::OBJECT)
2399  {
2400  const CEvaluationNodeObject* pObjectNode = dynamic_cast<const CEvaluationNodeObject*>(objectNodes[j]);
2401  assert(pObjectNode);
2402 
2403  if (pObjectNode == NULL) continue;
2404 
2405  std::vector<CCopasiContainer*> containers;
2406  containers.push_back(const_cast<CModel*>(dataModel.getModel()));
2407  const CCopasiObject* pObject =
2408  dataModel.ObjectFromName(containers, pObjectNode->getObjectCN());
2409  assert(pObject);
2410 
2411  if (pObject->isReference())
2412  {
2413  const CCopasiObject* pObjectParent = pObject->getObjectParent();
2414  assert(pObjectParent);
2415  std::string typeString = pObjectParent->getObjectType();
2416 
2417  if (typeString == "Compartment")
2418  {
2419  // must be a reference to the (transient) or initial volume
2420  if (initialExpression == true)
2421  {
2422  if (pObject->getObjectName() != "InitialVolume")
2423  {
2424  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "compartment", pObjectParent->getObjectName().c_str()));
2425  }
2426  }
2427  else
2428  {
2429  if (pObject->getObjectName() == "InitialVolume"
2430  && initialMap != NULL
2431  && (sbmlLevel > 2 || (sbmlLevel == 2 && sbmlVersion > 1)))
2432  {
2433  // add new parameter for the initial value
2434  addToInitialValueMap(initialMap, pObject, pObjectParent, sbmlLevel, sbmlVersion);
2435  }
2436  else if (pObject->getObjectName() != "Volume"
2437  && pObject->getObjectName() != "Rate")
2438  {
2439  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "compartment", pObjectParent->getObjectName().c_str()));
2440  }
2441  }
2442  }
2443  else if (typeString == "Metabolite")
2444  {
2445  // must be a reference to the transient or initial concentration
2446  if (initialExpression == true)
2447  {
2448  if (pObject->getObjectName() != "InitialConcentration" && pObject->getObjectName() != "InitialParticleNumber")
2449  {
2450  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "metabolite", pObjectParent->getObjectName().c_str()));
2451  }
2452  }
2453  else
2454  {
2455  if (pObject->getObjectName() == "InitialConcentration"
2456  && initialMap != NULL
2457  && (sbmlLevel > 2 || (sbmlLevel == 2 && sbmlVersion > 1)))
2458  {
2459  // add new parameter for the initial value
2460  addToInitialValueMap(initialMap, pObject, pObjectParent, sbmlLevel, sbmlVersion);
2461  }
2462  else if (pObject->getObjectName() != "Concentration"
2463  && pObject->getObjectName() != "ParticleNumber"
2464  && pObject->getObjectName() != "Rate")
2465  {
2466 
2467  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "metabolite", pObjectParent->getObjectName().c_str()));
2468  }
2469  }
2470  }
2471  else if (typeString == "ModelValue")
2472  {
2473  // must be a reference to the transient or initial value
2474  if (initialExpression == true)
2475  {
2476  if (pObject->getObjectName() != "InitialValue")
2477  {
2478  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "parameter", pObjectParent->getObjectName().c_str()));
2479  }
2480  }
2481  else
2482  {
2483  if (pObject->getObjectName() == "InitialValue"
2484  && initialMap != NULL
2485  && (sbmlLevel > 2 || (sbmlLevel == 2 && sbmlVersion > 1)))
2486  {
2487  // add new parameter for the initial value
2488  addToInitialValueMap(initialMap, pObject, pObjectParent, sbmlLevel, sbmlVersion);
2489  }
2490  else if (pObject->getObjectName() != "Value"
2491  && pObject->getObjectName() != "Rate")
2492  {
2493  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "parameter", pObjectParent->getObjectName().c_str()));
2494  }
2495  }
2496  }
2497  else if (typeString == "Model")
2498  {
2499  // must be a reference to the model time
2500  if (pObject->getObjectName() != "Time")
2501  {
2502  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "model", pObjectParent->getObjectName().c_str()));
2503  }
2504  }
2505  else if (typeString == "Parameter")
2506  {
2507  // must be a local parameter
2508  if (pObject->getObjectName() != "Value")
2509  {
2510  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "local parameter", pObjectParent->getObjectName().c_str()));
2511  }
2512  }
2513  else
2514  {
2515  if (sbmlLevel == 1 || (sbmlLevel == 2 && sbmlVersion == 1))
2516  {
2517  result.push_back(SBMLIncompatibility(10, pObject->getObjectName().c_str(), typeString.c_str(), pObjectParent->getObjectName().c_str()));
2518  }
2519  else
2520  {
2521  if (typeString == "Reaction")
2522  {
2523  if (pObject->getObjectName() != "Flux")
2524  {
2525  result.push_back(SBMLIncompatibility(1, pObject->getObjectName().c_str(), "reaction", pObjectParent->getObjectName().c_str()));
2526  }
2527  }
2528  }
2529  }
2530  }
2531  else
2532  {
2533  // normally local parameters are referenced via their value and
2534  // not directly, so this code should never be called
2535  const CCopasiParameter* pLocalParameter = dynamic_cast<const CCopasiParameter*>(pObject);
2536 
2537  if (pLocalParameter == NULL)
2538  {
2539  result.push_back(SBMLIncompatibility(1, "value", pObject->getObjectType().c_str() , pObject->getObjectName().c_str()));
2540  }
2541  }
2542  }
2543  }
2544 }
const std::string & getObjectName() const
const CRegisteredObjectName & getObjectCN() const
const std::string & getObjectType() const
static Type type(const Type &type)
void addToInitialValueMap(std::map< const std::string, Parameter * > *initialMap, const CCopasiObject *pObject, const CCopasiObject *pObjectParent, int sbmlLevel, int sbmlVersion)
bool isReference() const
CCopasiObject * ObjectFromName(const std::vector< CCopasiContainer * > &listOfContainer, const CCopasiObjectName &CN) const
CCopasiContainer * getObjectParent() const
void CSBMLExporter::collectIds ( const CCopasiDataModel dataModel,
std::map< std::string, const SBase * > &  idMap 
)
protected

This method goes through the given datamodel and collects all SBML ids.

Definition at line 7465 of file CSBMLExporter.cpp.

References CModel::getCompartments(), CModel::getEvents(), CCopasiRootContainer::getFunctionList(), CModel::getMetabolites(), CCopasiDataModel::getModel(), CModel::getModelValues(), CModel::getReactions(), CFunction::getSBMLId(), CModelEntity::getSBMLId(), CEvent::getSBMLId(), CReaction::getSBMLId(), CFunctionDB::loadedFunctions(), and CCopasiVector< T >::size().

Referenced by createSBMLDocument().

7466 {
7468  std::string id;
7469 
7470  for (i = 0; i < iMax; ++i)
7471  {
7473  id = pFun->getSBMLId();
7474 
7475  if (!id.empty())
7476  {
7477  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7478  }
7479  }
7480 
7481  const CModel* pModel = dataModel.getModel();
7482 
7483  id = pModel->getSBMLId();
7484 
7485  if (!id.empty())
7486  {
7487  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7488  }
7489 
7490  iMax = pModel->getCompartments().size();
7491 
7492  for (i = 0; i < iMax; ++i)
7493  {
7494  const CCompartment* pObj = pModel->getCompartments()[i];
7495  id = pObj->getSBMLId();
7496 
7497  if (!id.empty())
7498  {
7499  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7500  }
7501  }
7502 
7503  iMax = pModel->getMetabolites().size();
7504 
7505  for (i = 0; i < iMax; ++i)
7506  {
7507  const CMetab* pObj = pModel->getMetabolites()[i];
7508  id = pObj->getSBMLId();
7509 
7510  if (!id.empty())
7511  {
7512  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7513  }
7514  }
7515 
7516  iMax = pModel->getModelValues().size();
7517 
7518  for (i = 0; i < iMax; ++i)
7519  {
7520  const CModelValue* pObj = pModel->getModelValues()[i];
7521  id = pObj->getSBMLId();
7522 
7523  if (!id.empty())
7524  {
7525  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7526  }
7527  }
7528 
7529  iMax = pModel->getReactions().size();
7530 
7531  for (i = 0; i < iMax; ++i)
7532  {
7533  const CReaction* pObj = pModel->getReactions()[i];
7534  id = pObj->getSBMLId();
7535 
7536  if (!id.empty())
7537  {
7538  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7539  }
7540  }
7541 
7542  iMax = pModel->getEvents().size();
7543 
7544  for (i = 0; i < iMax; ++i)
7545  {
7546  const CEvent* pObj = pModel->getEvents()[i];
7547  id = pObj->getSBMLId();
7548 
7549  if (!id.empty())
7550  {
7551  idMap.insert(std::pair<const std::string, const SBase*>(id, (const SBase*)NULL));
7552  }
7553  }
7554 }
Definition: CEvent.h:152
CCopasiVectorN< CFunction > & loadedFunctions()
CCopasiVectorN< CEvent > & getEvents()
Definition: CModel.cpp:1110
const std::string & getSBMLId() const
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
const CCopasiVectorN< CModelValue > & getModelValues() const
Definition: CModel.cpp:1060
virtual size_t size() const
Definition: CMetab.h:178
const std::string & getSBMLId() const
Definition: CReaction.cpp:1654
static CFunctionDB * getFunctionList()
CCopasiVectorNS< CCompartment > & getCompartments()
Definition: CModel.cpp:1145
const std::string & getSBMLId() const
Definition: CFunction.cpp:68
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
const std::string & getSBMLId() const
Definition: CEvent.cpp:403
Definition: CModel.h:50
static void CSBMLExporter::convert_to_l1v1 ( std::string &  l1v2_string)
staticprotected

Converts the SBML model given in SBML Level 1 Version 2 format to SBML Level 1 Version 1. The method basically removes the namespace attribute on the sbml element and changes the version from 2 to 1. It also renames all "species" elements to "specie". All other changes between SBML Level 1 Version 2 and Level 1 Version 1 should not be relevant here.

Referenced by exportModelToString().

ASTNode * CSBMLExporter::convertASTTreeToLevel1 ( const ASTNode *  pNode,
const ListOfFunctionDefinitions &  functions,
std::string &  message 
)
staticprotected

Creates an ASTNode based tree where all occurences of nodes that are not supported in SBML Level 1 are replaced by supported constructs. On error an exception is created. The caller is responsible for freeing the memory of the returned object.

Definition at line 5507 of file CSBMLExporter.cpp.

References create_expression(), CCopasiMessage::EXCEPTION, MCSBML, and replaceL1IncompatibleNodes().

Referenced by convertToLevel1().

5508 {
5509  ASTNode* pExpanded = create_expression(pNode, &functions);
5510 
5511  if (pExpanded != NULL)
5512  {
5513  ASTNode* pReplaced = CSBMLExporter::replaceL1IncompatibleNodes(pExpanded);
5514  delete pExpanded;
5515 
5516  if (pReplaced == NULL)
5517  {
5518  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 62, message.c_str());
5519  }
5520 
5521  pExpanded = pReplaced;
5522  }
5523  else
5524  {
5525  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 61, message.c_str());
5526  }
5527 
5528  return pExpanded;
5529 }
static ASTNode * replaceL1IncompatibleNodes(const ASTNode *pNode)
#define MCSBML
ASTNode * create_expression(const ASTNode *pSource, const ListOfFunctionDefinitions *pFunctions)
ASTNode * CSBMLExporter::convertToASTNode ( const CEvaluationNode pOrig,
CCopasiDataModel dataModel 
)
protected

This converts an CEvaluationNode based tree to an ASTNode tree. It makes sure that all functions used in function calls already have a unique SBML id.

Definition at line 7078 of file CSBMLExporter.cpp.

References adjustNames(), mIdMap, mpSBMLDocument, pResult, setFunctionSBMLIds(), and CEvaluationNode::toAST().

Referenced by createEvent(), createFunctionDefinition(), createInitialAssignment(), createKineticLaw(), createRule(), and exportEventAssignments().

7079 {
7080  // first go through the tree and check that all function calls are to
7081  // functions that have an SBML id
7082  // if they don't, we have to set one
7083  this->setFunctionSBMLIds(pOrig, dataModel);
7084  ASTNode* pResult = pOrig->toAST(&dataModel);
7085 
7086  adjustNames(pResult, mpSBMLDocument, mIdMap);
7087 
7088  return pResult;
7089 }
virtual ASTNode * toAST(const CCopasiDataModel *pDataModel) const
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
const CArrayAnnotation * pResult
void adjustNames(ASTNode *node, SBMLDocument *pSBMLDocument, std::map< std::string, const SBase * > &idMap)
void setFunctionSBMLIds(const CEvaluationNode *pNode, CCopasiDataModel &dataModel)
void CSBMLExporter::convertToLevel1 ( )
protected

This method takes care of expanding all function calls in all expressions and converting functions that are not supported in Level 1 as well as constants that were not supported in Level 1

Definition at line 5230 of file CSBMLExporter.cpp.

References convertASTTreeToLevel1(), fatalError, mExportedFunctions, and mpSBMLDocument.

Referenced by createSBMLDocument().

5231 {
5232  // expand all function calls in rules, events and
5233  // kinetic laws and delete the functions
5234  // initial assignments do not need to be considered since they can not be
5235  // exported to Level 1 anyway
5236  //
5237  // checking of the resulting expressions for piecewise functions
5238  // is done in the convertASTTreeToLevel1 method
5239  if (this->mpSBMLDocument == NULL) return;
5240 
5241  Model* pModel = this->mpSBMLDocument->getModel();
5242  Rule* pRule = NULL;
5243  Reaction* pReaction = NULL;
5244  KineticLaw* pLaw = NULL;
5245  unsigned int i, iMax = pModel->getNumRules();
5246 
5247  for (i = 0; i < iMax; ++i)
5248  {
5249  pRule = pModel->getRule(i);
5250  assert(pRule != NULL);
5251  const ASTNode* pMath = pRule->getMath();
5252  assert(pMath != NULL);
5253  std::string message = "rule for object with id \"";
5254  message += pRule->getVariable();
5255  message += "\"";
5256  ASTNode* pNewMath = CSBMLExporter::convertASTTreeToLevel1(pMath, this->mExportedFunctions, message);
5257  assert(pNewMath != NULL);
5258 
5259  if (pNewMath != NULL)
5260  {
5261  pRule->setMath(pNewMath);
5262  delete pNewMath;
5263  }
5264  }
5265 
5266  iMax = pModel->getNumReactions();
5267 
5268  for (i = 0; i < iMax; ++i)
5269  {
5270  pReaction = pModel->getReaction(i);
5271  assert(pReaction != NULL);
5272  pLaw = pReaction->getKineticLaw();
5273 
5274  // maybe we don't have a kinetic law for all reactions
5275  if (pLaw != NULL)
5276  {
5277  const ASTNode* pMath = pLaw->getMath();
5278  assert(pMath != NULL);
5279  std::string message = "kinetic law in reaction with id \"";
5280  message += pReaction->getId();
5281  message += "\"";
5282  ASTNode* pNewMath = CSBMLExporter::convertASTTreeToLevel1(pMath, this->mExportedFunctions, message);
5283  assert(pNewMath != NULL);
5284 
5285  if (pNewMath != NULL)
5286  {
5287  pLaw->setMath(pNewMath);
5288  delete pNewMath;
5289  }
5290  else
5291  {
5292  fatalError();
5293  }
5294  }
5295  }
5296 }
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
ListOfFunctionDefinitions mExportedFunctions
Definition: CSBMLExporter.h:77
#define fatalError()
static ASTNode * convertASTTreeToLevel1(const ASTNode *pNode, const ListOfFunctionDefinitions &functions, std::string &message)
void CSBMLExporter::createAreaUnit ( const CCopasiDataModel dataModel)
protected

Creates the volume unit for the SBML model.

Creates the area unit for the SBML model.

Definition at line 798 of file CSBMLExporter.cpp.

References SBMLImporter::areSBMLUnitDefinitionsIdentical(), CModel::cm, CModel::dimensionlessLength, CModel::dm, CCopasiMessage::EXCEPTION, CModel::fm, CModel::getAreaUnitEnum(), CCopasiDataModel::getModel(), INIT_DEFAULTS, CModel::m, CModel::microm, CModel::mm, mpSBMLDocument, mSBMLLevel, mSBMLVersion, CModel::nm, and CModel::pm.

Referenced by createUnits().

799 {
800  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
801 
802  UnitDefinition uDef(this->mSBMLLevel, this->mSBMLVersion);
803  uDef.setName("area");
804  uDef.setId("area");
805  Unit unit(this->mSBMLLevel, this->mSBMLVersion);
806  INIT_DEFAULTS(unit);
807 
808  switch (dataModel.getModel()->getAreaUnitEnum())
809  {
810  case CModel::m:
811  unit.setKind(UNIT_KIND_METRE);
812  unit.setExponent(2);
813  unit.setScale(0);
814  break;
815 
816  case CModel::dm:
817  unit.setKind(UNIT_KIND_METRE);
818  unit.setExponent(2);
819  unit.setScale(-1);
820  break;
821 
822  case CModel::cm:
823  unit.setKind(UNIT_KIND_METRE);
824  unit.setExponent(2);
825  unit.setScale(-2);
826  break;
827 
828  case CModel::mm:
829  unit.setKind(UNIT_KIND_METRE);
830  unit.setExponent(2);
831  unit.setScale(-3);
832  break;
833 
834  case CModel::microm:
835  unit.setKind(UNIT_KIND_METRE);
836  unit.setExponent(2);
837  unit.setScale(-6);
838  break;
839 
840  case CModel::nm:
841  unit.setKind(UNIT_KIND_METRE);
842  unit.setExponent(2);
843  unit.setScale(-9);
844  break;
845 
846  case CModel::pm:
847  unit.setKind(UNIT_KIND_METRE);
848  unit.setExponent(2);
849  unit.setScale(-12);
850  break;
851 
852  case CModel::fm:
853  unit.setKind(UNIT_KIND_METRE);
854  unit.setExponent(2);
855  unit.setScale(-15);
856  break;
857 
859  unit.setKind(UNIT_KIND_DIMENSIONLESS);
860  unit.setExponent(1);
861  unit.setScale(0);
862  break;
863 
864  default:
865  CCopasiMessage(CCopasiMessage::EXCEPTION, "SBMLExporter Error: Unknown copasi area unit.");
866  break;
867  }
868 
869  unit.setMultiplier(1.0);
870  uDef.addUnit(&unit);
871  Model* pSBMLModel = this->mpSBMLDocument->getModel();
872  UnitDefinition* pUdef = pSBMLModel->getUnitDefinition("area");
873 
874  if (pUdef != NULL)
875  {
876  // check if it is the same unit as the existing one if there is one
877  // if yes, return, else replace the existing one
879  {
880  (*pUdef) = uDef;
881  }
882  }
883  else
884  {
885  // only add it if it is not the default unit definition anyway
886  if (this->mSBMLLevel > 2 ||
887  unit.getKind() != UNIT_KIND_METRE ||
888  unit.getScale() != 0 ||
889  unit.getExponent() != 2 ||
890  unit.getMultiplier() != 1.0)
891  {
892  // set the unit definition
893  pSBMLModel->addUnitDefinition(&uDef);
894  }
895  }
896 
897 // if we write an SBML L3 document, we have to explicitely set the units on the model
898 #if LIBSBML_VERSION >= 40100
899 
900  if (this->mSBMLLevel > 2)
901  {
902  pSBMLModel->setAreaUnits(uDef.getId());
903  }
904 
905 #endif // LIBSBML_VERSION
906 }
CModel::AreaUnit getAreaUnitEnum() const
Definition: CModel.cpp:2198
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
#define INIT_DEFAULTS(element)
static bool areSBMLUnitDefinitionsIdentical(const UnitDefinition *pUdef1, const UnitDefinition *pUdef2)
void CSBMLExporter::createCompartment ( CCompartment compartment)
protected

Creates the compartment for the given COPASI compartment.

Definition at line 928 of file CSBMLExporter.cpp.

References CModelEntity::ASSIGNMENT, createUniqueId(), fatalError, CCompartment::getDimensionality(), CModelEntity::getInitialExpression(), CModelEntity::getInitialValue(), CCopasiObject::getObjectName(), CModelEntity::getSBMLId(), CModelEntity::getStatus(), INIT_DEFAULTS, mAssignmentVector, mCOPASI2SBMLMap, mHandledSBMLObjects, mIdMap, mInitialAssignmentVector, mMetaIdMap, mODEVector, mpSBMLDocument, mSBMLLevel, CModelEntity::ODE, removeInitialAssignment(), removeRule(), CModelEntity::setSBMLId(), setSBMLNotes(), and updateMIRIAMAnnotation().

Referenced by createCompartments().

929 {
930  Compartment* pSBMLCompartment = NULL;
931  std::string sbmlId = compartment.getSBMLId();
932 
933  if (!sbmlId.empty())
934  {
935  pSBMLCompartment = this->mpSBMLDocument->getModel()->getCompartment(sbmlId);
936 
937  if (pSBMLCompartment == NULL)
938  {
939  pSBMLCompartment = this->mpSBMLDocument->getModel()->createCompartment();
940  this->mCOPASI2SBMLMap[&compartment] = pSBMLCompartment;
941  pSBMLCompartment->setId(sbmlId);
942  }
943  }
944  else
945  {
946  pSBMLCompartment = this->mpSBMLDocument->getModel()->createCompartment();
947  this->mCOPASI2SBMLMap[&compartment] = pSBMLCompartment;
948  sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, compartment.getObjectName(), false);
949  compartment.setSBMLId(sbmlId);
950  pSBMLCompartment->setId(sbmlId);
951  }
952 
953  INIT_DEFAULTS((*pSBMLCompartment));
954 
955  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, pSBMLCompartment));
956  this->mHandledSBMLObjects.insert(pSBMLCompartment);
957 
958  // don't call setName on level 1 objects because this will also
959  // change the id
960  if (this->mpSBMLDocument->getLevel() > 1)
961  {
962  pSBMLCompartment->setName(compartment.getObjectName().c_str());
963  }
964 
965  pSBMLCompartment->setSpatialDimensions((unsigned int)compartment.getDimensionality());
966  double value = compartment.getInitialValue();
967 
968  // if the value is NaN, unset the initial volume
969  if (!isnan(value))
970  {
971  pSBMLCompartment->setVolume(value);
972  }
973  else
974  {
975  pSBMLCompartment->unsetVolume();
976  }
977 
978  // fill assignment set
979  // a compartment can either have an assignment or an initial assignment but not
980  // both
981  CModelEntity::Status status = compartment.getStatus();
982 
983  if (status == CModelEntity::ASSIGNMENT)
984  {
985  if (compartment.getDimensionality() != 0)
986  {
987  this->mAssignmentVector.push_back(&compartment);
988  pSBMLCompartment->setConstant(false);
989  removeInitialAssignment(pSBMLCompartment->getId());
990  }
991  else
992  {
993  fatalError();
994  }
995  }
996  else if (status == CModelEntity::ODE)
997  {
998  if (compartment.getDimensionality() != 0)
999  {
1000  this->mODEVector.push_back(&compartment);
1001  pSBMLCompartment->setConstant(false);
1002 
1003  if (compartment.getInitialExpression() != "")
1004  {
1005  this->mInitialAssignmentVector.push_back(&compartment);
1006  }
1007  else
1008  {
1009  removeInitialAssignment(pSBMLCompartment->getId());
1010  }
1011  }
1012  else
1013  {
1014  fatalError();
1015  }
1016  }
1017  else
1018  {
1019  // do this explicitly since we might handle an existing object from an
1020  // earlier import that had it attribute set already
1021  if (this->mSBMLLevel != 1)
1022  {
1023  pSBMLCompartment->setConstant(true);
1024  }
1025  else
1026  {
1027  // Level 1 does not know the constant flag and libsbmnl does not drop
1028  // it automatically
1029  pSBMLCompartment->setConstant(false);
1030  }
1031 
1032  removeRule(pSBMLCompartment->getId());
1033 
1034  // fill initial assignment set
1035  if (compartment.getInitialExpression() != "")
1036  {
1037  if (compartment.getDimensionality() != 0)
1038  {
1039  this->mInitialAssignmentVector.push_back(&compartment);
1040  }
1041  else
1042  {
1043  fatalError();
1044  }
1045  }
1046  else
1047  {
1048  removeInitialAssignment(pSBMLCompartment->getId());
1049  }
1050  }
1051 
1052  if (pSBMLCompartment != NULL)
1053  {
1054  CSBMLExporter::setSBMLNotes(pSBMLCompartment, &compartment);
1055  }
1056 
1057  if (pSBMLCompartment != NULL && mSBMLLevel == 3)
1058  {
1059  pSBMLCompartment->setUnits("volume");
1060  }
1061 
1062  CSBMLExporter::updateMIRIAMAnnotation(&compartment, pSBMLCompartment, this->mMetaIdMap);
1063 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
const std::string & getObjectName() const
unsigned C_INT32 getDimensionality() const
#define fatalError()
std::vector< CModelEntity * > mAssignmentVector
Definition: CSBMLExporter.h:58
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
const C_FLOAT64 & getInitialValue() const
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
std::string getInitialExpression() const
void removeInitialAssignment(const std::string &sbmlId)
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
#define INIT_DEFAULTS(element)
std::set< SBase * > mHandledSBMLObjects
Definition: CSBMLExporter.h:62
const CModelEntity::Status & getStatus() const
void setSBMLId(const std::string &id)
void removeRule(const std::string &sbmlId)
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
void CSBMLExporter::createCompartments ( CCopasiDataModel dataModel)
protected

Creates the compartments for the model.

Definition at line 911 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), createCompartment(), CCopasiVector< T >::end(), CModel::getCompartments(), CCopasiDataModel::getModel(), and mpSBMLDocument.

Referenced by createSBMLDocument().

912 {
913  // make sure the SBML Document already exists and that it has a Model set
914  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
915 
917 
918  while (it != endit)
919  {
920  createCompartment(**it);
921  ++it;
922  }
923 }
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
void createCompartment(CCompartment &compartment)
iterator begin()
iterator end()
CCopasiVectorNS< CCompartment > & getCompartments()
Definition: CModel.cpp:1145
void CSBMLExporter::createEvent ( CEvent event,
Event *  pSBMLEvent,
CCopasiDataModel dataModel 
)
protected

Creates an SBML Event for the given COPASI event.

Definition at line 4005 of file CSBMLExporter.cpp.

References convertExpression(), convertToASTNode(), createFunctionSetFromFunctionNames(), createUniqueId(), CCopasiMessage::EXCEPTION, exportEventAssignments(), findDirectlyUsedFunctions(), CEvent::getDelayAssignment(), CCopasiRootContainer::getFunctionList(), CEvaluationTree::getInfix(), CCopasiObject::getObjectName(), CEvaluationTree::getRoot(), CEvent::getSBMLId(), CEvaluationNode::getType(), CEvaluationNode::INVALID, isExpressionSBMLCompatible(), mCOPASI2SBMLMap, MCSBML, mIdMap, mIncompatibilities, mIncompleteExport, mInitialValueMap, mMetaIdMap, mpSBMLDocument, mSBMLLevel, mSBMLVersion, mUsedFunctions, outputIncompatibilities(), replace_local_parameters(), replaceSpeciesReferences(), CEvaluationTree::setInfix(), setSBMLNotes(), CEvaluationNode::type(), updateMIRIAMAnnotation(), and CCopasiMessage::WARNING.

Referenced by createEvents().

4006 {
4007  // once events are functional, we create them here
4008  // don't forget to call replaceSpeciesReferences
4009  // on all mathematical expressions
4010 
4011  // first check if we already have a corresponding event from an earlier
4012  // import or export
4013  // if none is found, we create a new event object
4014  if (pSBMLEvent == NULL)
4015  {
4016  pSBMLEvent = this->mpSBMLDocument->getModel()->createEvent();
4017  }
4018  else
4019  {
4020  // Read the event to the model
4021  if (this->mpSBMLDocument->getModel()->getListOfEvents()->appendAndOwn(pSBMLEvent) != LIBSBML_OPERATION_SUCCESS)
4022  {
4023  // the existing event is not valid and cannot be added to the model, delete and create a new one instead
4024  delete pSBMLEvent;
4025  pSBMLEvent = this->mpSBMLDocument->getModel()->createEvent();
4026  }
4027  }
4028 
4029  // add the object to the COPASI2SBMLMap
4030  this->mCOPASI2SBMLMap[&event] = pSBMLEvent;
4031 
4032  // a) we set the name and the id
4033  if (!pSBMLEvent->isSetId())
4034  {
4035  std::string sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, event.getObjectName(), false);
4036  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, pSBMLEvent));
4037  pSBMLEvent->setId(sbmlId);
4038  event.setSBMLId(sbmlId);
4039  }
4040 
4041  // The attribute 'useValuesfromTriggerTime' is mandatory in L3V1
4042  if (this->mSBMLLevel > 2)
4043  {
4044  pSBMLEvent->setUseValuesFromTriggerTime(event.getDelayAssignment());
4045  }
4046 
4047 #if LIBSBML_VERSION >= 40200
4048 
4049  // if the event came from an SBML L3 model, we have to make sure that the
4050  // priority is not set when we export the event, otherwise the exported model
4051  // and the COPASI model will not behave the same.
4052  if (this->mSBMLLevel > 2)
4053  {
4054  pSBMLEvent->setPriority(NULL);
4055  }
4056 
4057 #endif // LIBSBML_VERSION >= 40200
4058 
4059  // if the name doesn't consists of whitespace only, we set the name
4060  if (event.getObjectName().find_first_not_of("\t\r\n ") != std::string::npos)
4061  {
4062  pSBMLEvent->setName(event.getObjectName());
4063  }
4064 
4065  // b) we check the trigger expression and export the trigger
4066  const CExpression* pExpression = event.getTriggerExpressionPtr();
4067  assert(pExpression != NULL);
4068  std::vector<SBMLIncompatibility> result;
4070  , dataModel
4071  , this->mSBMLLevel
4072  , this->mSBMLVersion
4073  , result
4074  , std::string("event trigger for event with id\"+" + event.getSBMLId() + "\"")
4075  , false
4076  , &mInitialValueMap);
4077 
4078  // collect directly used functions
4079  if (result.empty())
4080  {
4081  std::set<std::string> directlyUsedFunctionNames;
4082  CSBMLExporter::findDirectlyUsedFunctions(pExpression->getRoot(), directlyUsedFunctionNames);
4083  std::set<CFunction*> usedFunctions = CSBMLExporter::createFunctionSetFromFunctionNames(directlyUsedFunctionNames, CCopasiRootContainer::getFunctionList());
4084 
4085 # if defined _MSC_VER && _MSC_VER < 1201 // 1200 Identifies Visual C++ 6.0
4086  {
4087  std::set<CFunction*>::const_iterator it = usedFunctions.begin();
4088  std::set<CFunction*>::const_iterator end = usedFunctions.end();
4089 
4090  for (; it != end; ++it)
4091  this->mUsedFunctions.insert(*it);
4092  }
4093 #else
4094  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
4095 #endif
4096  }
4097  else
4098  {
4099  this->mIncompatibilities.insert(this->mIncompatibilities.end(), result.begin(), result.end());
4100 
4101  if (!this->mIncompleteExport)
4102  {
4103  this->outputIncompatibilities();
4104  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "trigger expression", "event", event.getObjectName().c_str());
4105  }
4106  }
4107 
4108  const std::string& changedExpression = convertExpression(pExpression->getInfix(), mInitialValueMap);
4109 
4110  CEvaluationTree tree;
4111 
4112  tree.setInfix(changedExpression);
4113 
4114  const CEvaluationNode* pOrigNode = tree.getRoot();
4115 
4116  //const CEvaluationNode* pOrigNode = pExpression->getRoot();
4117 
4119  {
4120  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 70, "trigger", "event", event.getObjectName().c_str());
4121  }
4122 
4123  // the next few lines replace references to species depending on whether
4124  // it is a reference to an amount or a reference to a concentration.
4125  // Other factors that influence this replacement are if the model
4126  // contains variable volumes or if the quantity units are set to CModel::number
4127  pOrigNode = this->replaceSpeciesReferences(pOrigNode, dataModel);
4128  assert(pOrigNode != NULL);
4129  ASTNode* pNode = this->convertToASTNode(pOrigNode, dataModel);
4130  delete pOrigNode;
4131  // convert local parameters that are referenced in an expression to global
4132  // parameters
4133  this->replace_local_parameters(pNode, dataModel);
4134 
4135  if (pNode != NULL)
4136  {
4137  Trigger* pTrigger = pSBMLEvent->createTrigger();
4138  pTrigger->setMath(pNode);
4139 #if LIBSBML_VERSION >= 40200
4140 
4141  // we need to make sure that the initial value of the trigger is set to true
4142  // as well as the persistent flag
4143  // for L3 event because otherwise the exported model will not do the same as
4144  // the model in COPASI
4145  if (this->mSBMLLevel > 2)
4146  {
4147  pTrigger->setInitialValue(true);
4148  pTrigger->setPersistent(true);
4149  }
4150 
4151 #endif // LIBSBML_VERSION >= 40200
4152  delete pNode;
4153  }
4154  else
4155  {
4156  if (this->mIncompleteExport != true)
4157  {
4158  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "trigger", "event", event.getObjectName().c_str());
4159  }
4160  }
4161 
4162  // c) we check the delay expression and export it if it is set
4163  pExpression = event.getDelayExpressionPtr();
4164  const std::string delayInfix = pExpression == NULL ? "" : pExpression->getInfix();
4165 
4166  if (!delayInfix.empty())
4167  {
4168  result.clear();
4170  , dataModel
4171  , this->mSBMLLevel
4172  , this->mSBMLVersion
4173  , result
4174  , std::string("event delay for event with id\"+" + event.getSBMLId() + "\"").c_str()
4175  , false
4176  , &mInitialValueMap);
4177 
4178  // collect directly used functions
4179  if (result.empty())
4180  {
4181  std::set<std::string> directlyUsedFunctionNames;
4182  CSBMLExporter::findDirectlyUsedFunctions(pExpression->getRoot(), directlyUsedFunctionNames);
4183  std::set<CFunction*> usedFunctions = CSBMLExporter::createFunctionSetFromFunctionNames(directlyUsedFunctionNames, CCopasiRootContainer::getFunctionList());
4184 
4185 # if defined _MSC_VER && _MSC_VER < 1201 // 1200 Identifies Visual C++ 6.0
4186  {
4187  it = usedFunctions.begin();
4188  usedFunctions.end();
4189 
4190  for (; it != end; ++it)
4191  this->mUsedFunctions.insert(*it);
4192  }
4193 #else
4194  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
4195 #endif
4196  }
4197  else
4198  {
4199  this->mIncompatibilities.insert(this->mIncompatibilities.end(), result.begin(), result.end());
4200 
4201  if (!this->mIncompleteExport)
4202  {
4203  this->outputIncompatibilities();
4204  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "delay expression", "event", event.getObjectName().c_str());
4205  }
4206  }
4207 
4208  //pOrigNode = pExpression->getRoot();
4209  const std::string& changedExpression = convertExpression(pExpression->getInfix(), mInitialValueMap);
4210  CEvaluationTree tree;
4211  tree.setInfix(changedExpression);
4212  const CEvaluationNode* pOrigNode = tree.getRoot();
4213 
4215  {
4216  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 70, "delay", "event", event.getObjectName().c_str());
4217  }
4218 
4219  // the next few lines replace references to species depending on whether
4220  // it is a reference to an amount or a reference to a concentration.
4221  // Other factors that influence this replacement are if the model
4222  // contains variable volumes or if the quantity units are set to CModel::number
4223  pOrigNode = this->replaceSpeciesReferences(pOrigNode, dataModel);
4224  assert(pOrigNode != NULL);
4225  pNode = this->convertToASTNode(pOrigNode, dataModel);
4226  delete pOrigNode;
4227  // convert local parameters that are referenced in an expression to global
4228  // parameters
4229  this->replace_local_parameters(pNode, dataModel);
4230 
4231  if (pNode != NULL)
4232  {
4233  Delay* pDelay = new Delay(this->mSBMLLevel, this->mSBMLVersion);
4234  pDelay->setMath(pNode);
4235  pSBMLEvent->setDelay(pDelay);
4236  delete pNode;
4237  delete pDelay;
4238 
4239  if (this->mSBMLLevel == 2 && this->mSBMLVersion >= 4)
4240  {
4241  pSBMLEvent->setUseValuesFromTriggerTime(event.getDelayAssignment());
4242  }
4243  // if the delayAssignment is set to false, we have a problem
4244  // because the model semantic changes on export
4245  else if (event.getDelayAssignment() == false &&
4246  this->mSBMLLevel <= 2 &&
4247  this->mSBMLVersion <= 3)
4248  {
4249  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 77, event.getObjectName().c_str(), this->mSBMLLevel, this->mSBMLVersion);
4250  }
4251  }
4252  else
4253  {
4254  if (this->mIncompleteExport != true)
4255  {
4256  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "delay", "event", event.getObjectName().c_str());
4257  }
4258  }
4259  }
4260 
4261  // export all event assignments
4262  this->exportEventAssignments(event, pSBMLEvent, dataModel);
4263 
4264  // check if the event has event assignments, if not, we have to delete
4265  // the event and create an error message (for SBML Levels < 3)
4266  if (pSBMLEvent->getNumEventAssignments() == 0 && mpSBMLDocument->getLevel() < 3)
4267  {
4268  unsigned int i, iMax = this->mpSBMLDocument->getModel()->getNumEvents();
4269 
4270  // the following code does not check if the corrct pointer is found
4271  // but this should not be a problem
4272  for (i = 0; i < iMax; ++i)
4273  {
4274  if (this->mpSBMLDocument->getModel()->getEvent(i) == pSBMLEvent)
4275  {
4276  this->mpSBMLDocument->getModel()->getListOfEvents()->remove(i);
4277  }
4278  }
4279 
4280  delete pSBMLEvent;
4281  this->mCOPASI2SBMLMap.erase(&event);
4282  pSBMLEvent = NULL;
4283 
4284  CCopasiMessage(CCopasiMessage::WARNING, "The event '%s' contained no event assignments, this is only supported for SBML Level 3 onwards. The event has not been exported.", event.getObjectName().c_str());
4285  }
4286 
4287  if (pSBMLEvent != NULL)
4288  {
4289  CSBMLExporter::setSBMLNotes(pSBMLEvent, &event);
4290  CSBMLExporter::updateMIRIAMAnnotation(&event, pSBMLEvent, this->mMetaIdMap);
4291  }
4292 }
static void findDirectlyUsedFunctions(const CEvaluationNode *pRootNode, std::set< std::string > &result)
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
const bool & getDelayAssignment() const
Definition: CEvent.cpp:419
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
void replace_local_parameters(ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
std::string convertExpression(const std::string &expression, const std::map< const std::string, Parameter * > &initialValueMap)
const std::string & getObjectName() const
const Type & getType() const
bool mIncompleteExport
Definition: CSBMLExporter.h:66
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
std::map< const std::string, Parameter * > mInitialValueMap
Definition: CSBMLExporter.h:79
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
static Type type(const Type &type)
#define MCSBML
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
void exportEventAssignments(const CEvent &event, Event *pSBMLEvent, CCopasiDataModel &dataModel)
static CFunctionDB * getFunctionList()
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
ASTNode * convertToASTNode(const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
static void isExpressionSBMLCompatible(const CEvaluationTree &expr, const CCopasiDataModel &dataModel, int sbmlLevel, int sbmlVersion, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription, bool initialExression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
CEvaluationNode * replaceSpeciesReferences(const CEvaluationNode *pOrigNode, const CCopasiDataModel &dataModel)
void outputIncompatibilities() const
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
const std::string & getSBMLId() const
Definition: CEvent.cpp:403
static const std::set< CFunction * > createFunctionSetFromFunctionNames(const std::set< std::string > &names, CFunctionDB *pFunDB)
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
CEvaluationNode * getRoot()
const std::string & getInfix() const
virtual bool setInfix(const std::string &infix)
void CSBMLExporter::createEvents ( CCopasiDataModel dataModel)
protected

Creates the events for the given data model.

Definition at line 3938 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), checkForEvents(), createEvent(), CCopasiVector< T >::end(), CModel::getEvents(), CCopasiDataModel::getModel(), mCOPASI2SBMLMap, mIncompatibilities, mpSBMLDocument, and mSBMLLevel.

Referenced by createSBMLDocument().

3939 {
3940  if (this->mSBMLLevel == 1)
3941  {
3943  return;
3944  }
3945 
3946  // bail early
3947  if (dataModel.getModel() == NULL)
3948  return;
3949 
3950  Model* pSBMLModel = this->mpSBMLDocument->getModel();
3951 
3952  if (pSBMLModel == NULL)
3953  return;
3954 
3955  // remove all events from the SBML model and put them in a set
3956  std::set<Event*> eventSet;
3957 
3958  while (pSBMLModel->getNumEvents() != 0)
3959  {
3960  Event* pEvent = pSBMLModel->getListOfEvents()->remove(pSBMLModel->getNumEvents() - 1);
3961  assert(pEvent != NULL);
3962  eventSet.insert(pEvent);
3963  }
3964 
3965  const CCopasiVectorN<CEvent>& events = dataModel.getModel()->getEvents();
3966 
3967  CCopasiVectorN<CEvent>::const_iterator it = events.begin(), endit = events.end();
3968 
3969  Event* pSBMLEvent = NULL;
3970 
3971  std::map<const CCopasiObject*, SBase*>::const_iterator pos;
3972 
3973  while (it != endit)
3974  {
3975  // find the old event if there is one
3976  pos = this->mCOPASI2SBMLMap.find(*it);
3977 
3978  if (pos != this->mCOPASI2SBMLMap.end())
3979  {
3980  pSBMLEvent = dynamic_cast<Event*>(pos->second);
3981  }
3982  else
3983  {
3984  pSBMLEvent = NULL;
3985  }
3986 
3987  // remove the event from the set
3988  if (pSBMLEvent) eventSet.erase(pSBMLEvent);
3989 
3990  this->createEvent(**it, pSBMLEvent, dataModel);
3991  ++it;
3992  }
3993 
3994  // make sure events that have already been deleted do not get
3995  // exported
3996  std::set<Event*>::iterator it2 = eventSet.begin(), endit2 = eventSet.end();
3997 
3998  while (it2 != endit2)
3999  {
4000  delete *it2;
4001  ++it2;
4002  }
4003 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
CCopasiVectorN< CEvent > & getEvents()
Definition: CModel.cpp:1110
iterator begin()
iterator end()
static void checkForEvents(const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
void createEvent(CEvent &event, Event *pSBMLEvent, CCopasiDataModel &dataModel)
void CSBMLExporter::createFunctionDefinition ( CFunction function,
CCopasiDataModel dataModel 
)
protected

Create the SBML function definition from the given COPASI function.

Definition at line 3107 of file CSBMLExporter.cpp.

References convertToASTNode(), createUniqueId(), CCopasiMessage::EXCEPTION, isExpressionSBMLCompatible(), isValidSId(), mCOPASI2SBMLMap, MCSBML, mExportedFunctions, mFunctionMap, mIdMap, mIncompatibilities, mMetaIdMap, mpSBMLDocument, mSBMLLevel, mSBMLVersion, setSBMLNotes(), CFunctionParameters::size(), updateMIRIAMAnnotation(), and CCopasiMessage::WARNING.

Referenced by createFunctionDefinitions().

3108 {
3109  // check the expression
3110  std::map<const CCopasiObject*, SBase*>::iterator pos = this->mCOPASI2SBMLMap.find(&function);
3111  FunctionDefinition* pFunDef = NULL;
3112 
3113  // the entry could be NULL when exporting to L2 first and then to L3 because the
3114  // SBMLExporter::collectIds will add a NULL entry into the id table which will be
3115  // tranferred to the COPASI2SBMLMap.
3116  if (pos != this->mCOPASI2SBMLMap.end() && pos->second != NULL)
3117  {
3118  pFunDef = dynamic_cast<FunctionDefinition*>(pos->second);
3119  assert(pFunDef);
3120  this->mpSBMLDocument->getModel()->getListOfFunctionDefinitions()->appendAndOwn(pFunDef);
3121  }
3122  else
3123  {
3124  if (this->mpSBMLDocument->getLevel() == 1)
3125  {
3126  pFunDef = new FunctionDefinition(2, 4);
3127  }
3128  else
3129  {
3130  pFunDef = new FunctionDefinition(this->mpSBMLDocument->getLevel(), this->mpSBMLDocument->getVersion());
3131  }
3132 
3133  this->mFunctionMap[pFunDef] = &function;
3134  pFunDef->setName(function.getObjectName());
3135  std::string id = function.getSBMLId();
3136 
3137  if (id.empty())
3138  {
3139  id = function.getObjectName();
3140 
3141  if (CSBMLExporter::isValidSId(id))
3142  {
3143  if (this->mIdMap.find(id) != this->mIdMap.end())
3144  {
3145  id = CSBMLExporter::createUniqueId(this->mIdMap, id, true);
3146  }
3147  }
3148  else
3149  {
3150  id = CSBMLExporter::createUniqueId(this->mIdMap, function.getObjectName(), false);
3151  }
3152  }
3153 
3154  this->mIdMap.insert(std::pair<const std::string, const SBase*>(id, pFunDef));
3155  pFunDef->setId(id);
3156  function.setSBMLId(id);
3157  this->mCOPASI2SBMLMap[&function] = pFunDef;
3158  }
3159 
3160  if (function.getRoot() == NULL)
3161  {
3162  std::string errorMessage = std::string("Can not export function '");
3163  errorMessage += function.getObjectName();
3164  errorMessage += std::string("'. Function does not have a valid root node.");
3165  CCopasiMessage(CCopasiMessage::EXCEPTION, errorMessage.c_str());
3166  }
3167  else
3168  {
3169  std::vector<SBMLIncompatibility> result;
3170  CSBMLExporter::isExpressionSBMLCompatible(function, dataModel, this->mSBMLLevel, this->mSBMLVersion, result, std::string("function with name \"" + function.getObjectName() + "\"").c_str());
3171 
3172  if (result.empty())
3173  {
3174  ASTNode* pFunNode = this->convertToASTNode(function.getRoot(), dataModel);
3175  // go through the AST tree and replace all function call nodes with with a call to the sbml id
3176  ASTNode* pLambda = new ASTNode(AST_LAMBDA);
3177  // add the parameters to the function definition
3178  const CFunctionParameters& funParams = function.getVariables();
3179  size_t i, iMax = funParams.size();
3180  ASTNode* pParamNode = NULL;
3181 
3182  for (i = 0; i < iMax; ++i)
3183  {
3184  pParamNode = new ASTNode(AST_NAME);
3185  pParamNode->setName(funParams[i]->getObjectName().c_str());
3186  pLambda->addChild(pParamNode);
3187  }
3188 
3189  pLambda->addChild(pFunNode);
3190 
3191  if (pFunDef->setMath(pLambda) != LIBSBML_OPERATION_SUCCESS)
3192  {
3194  "The function '%s' uses an invalid expression '%s' that cannot be exported to SBML, the function definition is not exported."
3195  , function.getObjectName().c_str()
3196  , function.getInfix().c_str());
3197  }
3198 
3199  this->mExportedFunctions.appendAndOwn(pFunDef);
3200  delete pLambda;
3201  }
3202  else
3203  {
3204  this->mIncompatibilities.insert(this->mIncompatibilities.end(), result.begin(), result.end());
3205  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 28, function.getObjectName().c_str());
3206  }
3207  }
3208 
3209  if (pFunDef != NULL)
3210  {
3211  CSBMLExporter::setSBMLNotes(pFunDef, &function);
3212  }
3213 
3214  CSBMLExporter::updateMIRIAMAnnotation(&function, pFunDef, this->mMetaIdMap);
3215 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
ListOfFunctionDefinitions mExportedFunctions
Definition: CSBMLExporter.h:77
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
#define MCSBML
std::map< const FunctionDefinition *, const CCopasiObject * > mFunctionMap
Definition: CSBMLExporter.h:78
static bool isValidSId(const std::string &id)
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
ASTNode * convertToASTNode(const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
static void isExpressionSBMLCompatible(const CEvaluationTree &expr, const CCopasiDataModel &dataModel, int sbmlLevel, int sbmlVersion, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription, bool initialExression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
void CSBMLExporter::createFunctionDefinitions ( CCopasiDataModel dataModel)
protected

Create all function definitions.

Definition at line 2940 of file CSBMLExporter.cpp.

References createFunctionDefinition(), fatalError, findUsedFunctions(), CCopasiRootContainer::getFunctionList(), CCopasiObject::getObjectName(), mCOPASI2SBMLMap, mExportedFunctions, mFunctionMap, mpSBMLDocument, and mUsedFunctions.

Referenced by createSBMLDocument().

2941 {
2942  this->mExportedFunctions.clear(true);
2943  this->mFunctionMap.clear();
2944  // make sure the list of used functions is filled before this is
2945  // called
2946  // make sure the mCOPASI2SBMLMap is up to date
2947 
2948  // find all indirectly called functions
2949  std::vector<CFunction*> usedFunctions = findUsedFunctions(this->mUsedFunctions, CCopasiRootContainer::getFunctionList());
2950  this->mUsedFunctions.clear();
2951  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
2952 
2953  // remove the function calls that have been created by copasi solely for use
2954  // as a kinetic law term if it is no longer needed
2955  Model* pModel = this->mpSBMLDocument->getModel();
2956  assert(pModel);
2957 
2958  if (pModel == NULL) fatalError();
2959 
2960  std::map<SBase*, const CCopasiObject*> sbml2copasiMap;
2961  std::map<const CCopasiObject*, SBase*>::iterator mapIt = this->mCOPASI2SBMLMap.begin();
2962  std::map<const CCopasiObject*, SBase*>::iterator mapEndit = this->mCOPASI2SBMLMap.end();
2963 
2964  while (mapIt != mapEndit)
2965  {
2966  sbml2copasiMap.insert(std::make_pair(mapIt->second, mapIt->first));
2967  ++mapIt;
2968  }
2969 
2970  std::set<CFunction*> unusedFunctions;
2971  unsigned int i = 0, iMax = pModel->getNumFunctionDefinitions();
2972  std::map<SBase*, const CCopasiObject*>::iterator mapPos;
2973  std::set<std::string> toRemove;
2974 
2975  while (i < iMax)
2976  {
2977  FunctionDefinition* pFunDef = pModel->getFunctionDefinition(i);
2978 
2979  if (pFunDef != NULL)
2980  {
2981  mapPos = sbml2copasiMap.find(pFunDef);
2982 
2983  if (mapPos != sbml2copasiMap.end())
2984  {
2985  CFunction* pFun = dynamic_cast<CFunction*>(const_cast<CCopasiObject*>(mapPos->second));
2986 
2987  if (pFun != NULL && this->mUsedFunctions.find(pFun) == this->mUsedFunctions.end())
2988  {
2989  // the function exists in the model, but it is not used in any
2990  // expression
2991  if (pFun->getObjectName().find("function_4_") == 0 || pFun->getObjectName().find("Function for ") == 0)
2992  {
2993  // store the function definition that is to be removed
2994  toRemove.insert(pFunDef->getId());
2995  }
2996  else
2997  {
2998  // those need to be stored in a separate list since we also
2999  // need to find indirectly called functions
3000  unusedFunctions.insert(pFun);
3001  }
3002  }
3003  }
3004  }
3005 
3006  ++i;
3007  }
3008 
3009  // find all indirectly called functions for the unused functions
3010  std::vector<CFunction*> functionsVect = findUsedFunctions(unusedFunctions, CCopasiRootContainer::getFunctionList());
3011  usedFunctions.insert(usedFunctions.end(), functionsVect.begin(), functionsVect.end());
3012  // reset the used functions set
3013  this->mUsedFunctions.clear();
3014  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
3015 
3016  // now we remove the function definitions from the SBML model
3017  std::set<std::string>::iterator toRemoveIt = toRemove.begin();
3018  std::set<std::string>::iterator toRemoveEndit = toRemove.end();
3019 
3020  while (toRemoveIt != toRemoveEndit)
3021  {
3022  FunctionDefinition* pFunDef = pModel->getFunctionDefinition(*toRemoveIt);
3023 
3024  if (pFunDef != NULL)
3025  {
3026  mapPos = sbml2copasiMap.find(pFunDef);
3027 
3028  if (mapPos != sbml2copasiMap.end() &&
3029  this->mUsedFunctions.find(dynamic_cast<CFunction*>(const_cast<CCopasiObject*>(mapPos->second))) == this->mUsedFunctions.end())
3030  {
3031  pModel->getListOfFunctionDefinitions()->remove(*toRemoveIt);
3032  }
3033  }
3034 
3035  ++toRemoveIt;
3036  }
3037 
3038  // order the remaining function definitions
3039  // remove duplicates from the vector, always keep the last one
3040  std::vector<CFunction*>::reverse_iterator reverseIt = usedFunctions.rbegin(), reverseEndit = usedFunctions.rend();
3041  functionsVect.clear();
3042 
3043  while (reverseIt != reverseEndit)
3044  {
3045  if (std::find(functionsVect.begin(), functionsVect.end(), *reverseIt) == functionsVect.end())
3046  {
3047  functionsVect.insert(functionsVect.begin(), *reverseIt);
3048  }
3049 
3050  ++reverseIt;
3051  }
3052 
3053  // remove all existing function definitions from the list
3054  // and remove their entries from the copasi2sbmlmap
3055  iMax = pModel->getNumFunctionDefinitions();
3056 
3057  for (unsigned int i = 0; i < iMax; ++i)
3058  {
3059  mapIt = this->mCOPASI2SBMLMap.begin();
3060  mapEndit = this->mCOPASI2SBMLMap.end();
3061 
3062  while (mapIt != mapEndit)
3063  {
3064  if (mapIt->second == pModel->getFunctionDefinition(i))
3065  {
3066  this->mCOPASI2SBMLMap.erase(mapIt->first);
3067  break;
3068  }
3069 
3070  ++mapIt;
3071  }
3072  }
3073 
3074  // don't want to remove the new custom function definitions if present
3075  // pModel->getListOfFunctionDefinitions()->clear(true);
3076  for (int i = ((int)pModel->getNumFunctionDefinitions()) - 1; i >= 0; --i)
3077  {
3078  FunctionDefinition* current = pModel->getFunctionDefinition(i);
3079 
3080  if (current != NULL &&
3081  current->isSetAnnotation() &&
3082  current->getAnnotation()->getNumChildren() == 1 &&
3083  current->getAnnotation()->getChild(0).getURI().find("http://sbml.org/annotations/") != std::string::npos)
3084  continue;
3085 
3086  // if we are here it is not one of the custom ones, so delete it
3087  FunctionDefinition* toDelete = pModel->removeFunctionDefinition(i);
3088  delete toDelete;
3089  }
3090 
3091  std::vector<CFunction*>::iterator it = functionsVect.begin(), endit = functionsVect.end();
3092 
3093  while (it != endit)
3094  {
3095  if (*it != NULL)
3096  {
3097  createFunctionDefinition(**it, dataModel);
3098  }
3099 
3100  ++it;
3101  }
3102 }
static const std::vector< CFunction * > findUsedFunctions(std::set< CFunction * > &functions, CFunctionDB *pFunctionDB)
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
ListOfFunctionDefinitions mExportedFunctions
Definition: CSBMLExporter.h:77
const std::string & getObjectName() const
void createFunctionDefinition(CFunction &function, CCopasiDataModel &dataModel)
#define fatalError()
std::map< const FunctionDefinition *, const CCopasiObject * > mFunctionMap
Definition: CSBMLExporter.h:78
static CFunctionDB * getFunctionList()
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
const std::set< CFunction * > CSBMLExporter::createFunctionSetFromFunctionNames ( const std::set< std::string > &  names,
CFunctionDB pFunDB 
)
staticprotected

Definition at line 5054 of file CSBMLExporter.cpp.

References CCopasiMessage::ERROR, CFunctionDB::findFunction(), and MCSBML.

Referenced by checkForPiecewiseFunctions(), createEvent(), createInitialAssignment(), createRule(), exportEventAssignments(), and findUsedFunctions().

5055 {
5056  std::set<CFunction*> result;
5057 
5058  if (pFunDB != NULL)
5059  {
5060  std::set<std::string>::const_iterator it = names.begin();
5061  std::set<std::string>::const_iterator endit = names.end();
5062  CFunction* pFun = NULL;
5063 
5064  while (it != endit)
5065  {
5066  pFun = dynamic_cast<CFunction*>(pFunDB->findFunction(*it));
5067 
5068  if (pFun == NULL)
5069  {
5070  CCopasiMessage(CCopasiMessage::ERROR, MCSBML + 15, (*it).c_str());
5071  }
5072  else
5073  {
5074  result.insert(pFun);
5075  }
5076 
5077  ++it;
5078  }
5079  }
5080 
5081  return result;
5082 }
#define MCSBML
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
CFunction * findFunction(const std::string &functionName)
const std::map< std::string, const SBase * > CSBMLExporter::createIdMap ( const Model &  sbmlModel)
protected

Goes through the given SBML model and puts all ids with the corresponding object into a map.

Definition at line 2075 of file CSBMLExporter.cpp.

2076 {
2077  // go through all function definitions, compartments, species, reactions,
2078  // parameters and events and create a set with all used ids.
2079  std::map<std::string, const SBase*> idMap;
2080  unsigned int i, iMax;
2081 
2082  if (sbmlModel.isSetId())
2083  {
2084  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getId(), &sbmlModel));
2085  }
2086 
2087  if (sbmlModel.getListOfFunctionDefinitions()->isSetId())
2088  {
2089  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfFunctionDefinitions()->getId(), sbmlModel.getListOfFunctionDefinitions()));
2090  }
2091 
2092  iMax = sbmlModel.getNumFunctionDefinitions();
2093 
2094  for (i = 0; i < iMax; ++i)
2095  {
2096  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getFunctionDefinition(i)->getId(), sbmlModel.getFunctionDefinition(i)));
2097  }
2098 
2099  if (sbmlModel.getListOfCompartments()->isSetId())
2100  {
2101  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfCompartments()->getId(), sbmlModel.getListOfCompartments()));
2102  }
2103 
2104  iMax = sbmlModel.getNumCompartments();
2105 
2106  for (i = 0; i < iMax; ++i)
2107  {
2108  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getCompartment(i)->getId(), sbmlModel.getCompartment(i)));
2109  }
2110 
2111  if (sbmlModel.getListOfSpecies()->isSetId())
2112  {
2113  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfSpecies()->getId(), sbmlModel.getListOfSpecies()));
2114  }
2115 
2116  iMax = sbmlModel.getNumSpecies();
2117 
2118  for (i = 0; i < iMax; ++i)
2119  {
2120  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getSpecies(i)->getId(), sbmlModel.getSpecies(i)));
2121  }
2122 
2123  if (sbmlModel.getListOfParameters()->isSetId())
2124  {
2125  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfParameters()->getId(), sbmlModel.getListOfParameters()));
2126  }
2127 
2128  iMax = sbmlModel.getNumParameters();
2129 
2130  for (i = 0; i < iMax; ++i)
2131  {
2132  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getParameter(i)->getId(), sbmlModel.getParameter(i)));
2133  }
2134 
2135  if (sbmlModel.getListOfReactions()->isSetId())
2136  {
2137  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfReactions()->getId(), sbmlModel.getListOfReactions()));
2138  }
2139 
2140  iMax = sbmlModel.getNumReactions();
2141 
2142  for (i = 0; i < iMax; ++i)
2143  {
2144  const Reaction* pReaction = sbmlModel.getReaction(i);
2145 
2146  if (pReaction != NULL)
2147  {
2148  idMap.insert(std::pair<const std::string, const SBase*>(pReaction->getId(), pReaction));
2149 
2150  if (pReaction->getListOfReactants()->isSetId())
2151  {
2152  idMap.insert(std::pair<const std::string, const SBase*>(pReaction->getListOfReactants()->getId(), pReaction->getListOfReactants()));
2153  }
2154 
2155  unsigned int j, jMax = pReaction->getNumReactants();
2156  const SpeciesReference* pSRef = NULL;
2157 
2158  for (j = 0; j < jMax; ++j)
2159  {
2160  pSRef = pReaction->getReactant(j);
2161 
2162  if (pSRef->isSetId())
2163  {
2164  idMap.insert(std::pair<const std::string, const SBase*>(pSRef->getId(), pSRef));
2165  }
2166  }
2167 
2168  if (pReaction->getListOfProducts()->isSetId())
2169  {
2170  idMap.insert(std::pair<const std::string, const SBase*>(pReaction->getListOfProducts()->getId(), pReaction->getListOfProducts()));
2171  }
2172 
2173  jMax = pReaction->getNumProducts();
2174 
2175  for (j = 0; j < jMax; ++j)
2176  {
2177  pSRef = pReaction->getProduct(j);
2178 
2179  if (pSRef->isSetId())
2180  {
2181  idMap.insert(std::pair<const std::string, const SBase*>(pSRef->getId(), pSRef));
2182  }
2183  }
2184 
2185  if (pReaction->getListOfModifiers()->isSetId())
2186  {
2187  idMap.insert(std::pair<const std::string, const SBase*>(pReaction->getListOfModifiers()->getId(), pReaction->getListOfModifiers()));
2188  }
2189 
2190  jMax = pReaction->getNumModifiers();
2191  const ModifierSpeciesReference* pModSRef;
2192 
2193  for (j = 0; j < jMax; ++j)
2194  {
2195  pModSRef = pReaction->getModifier(j);
2196 
2197  if (pModSRef->isSetId())
2198  {
2199  idMap.insert(std::pair<const std::string, const SBase*>(pModSRef->getId(), pModSRef));
2200  }
2201  }
2202  }
2203  }
2204 
2205  if (sbmlModel.getListOfEvents()->isSetId())
2206  {
2207  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getListOfEvents()->getId(), sbmlModel.getListOfEvents()));
2208  }
2209 
2210  iMax = sbmlModel.getNumEvents();
2211 
2212  for (i = 0; i < iMax; ++i)
2213  {
2214  idMap.insert(std::pair<const std::string, const SBase*>(sbmlModel.getEvent(i)->getId(), sbmlModel.getEvent(i)));
2215  }
2216 
2217  // if COPASI is compiled with layout, we have to add those ids as well
2218  const LayoutModelPlugin* lmPlugin = (LayoutModelPlugin*)sbmlModel.getPlugin("layout");
2219 
2220  if (lmPlugin != NULL)
2221  {
2222  if (lmPlugin->getListOfLayouts()->isSetId())
2223  {
2224  idMap.insert(std::pair<const std::string, const SBase*>(lmPlugin->getListOfLayouts()->getId(), lmPlugin->getListOfLayouts()));
2225  }
2226 
2227  iMax = lmPlugin->getListOfLayouts()->size();
2228 
2229  for (i = 0; i < iMax; ++i)
2230  {
2231  const Layout* pLayout = lmPlugin->getLayout(i);
2232 
2233  if (pLayout != NULL)
2234  {
2235  if (pLayout->isSetId())
2236  {
2237  idMap.insert(std::pair<const std::string, const SBase*>(pLayout->getId(), pLayout));
2238  }
2239  }
2240  }
2241  }
2242 
2243  return idMap;
2244 }
void CSBMLExporter::createInitialAssignment ( const CModelEntity modelEntity,
CCopasiDataModel dataModel 
)
protected

Creates the initial assignment for the given COPASI model entity.

Definition at line 1673 of file CSBMLExporter.cpp.

References convertToASTNode(), createFunctionSetFromFunctionNames(), CCopasiMessage::EXCEPTION, findDirectlyUsedFunctions(), CMetab::getCompartment(), CCompartment::getDimensionality(), CCopasiRootContainer::getFunctionList(), CModelEntity::getInitialExpressionPtr(), CModelEntity::getInitialValueReference(), CCopasiObject::getObjectName(), CCopasiObject::getObjectType(), CEvaluationTree::getRoot(), CModelEntity::getSBMLId(), CEvaluationNode::getType(), CEvaluationNode::INVALID, isExpressionSBMLCompatible(), mCOPASI2SBMLMap, MCSBML, mHandledSBMLObjects, mIncompatibilities, mIncompleteExport, mInitialValueMap, mpSBMLDocument, mSBMLLevel, mSBMLVersion, multiplyByObject(), mUsedFunctions, outputIncompatibilities(), replace_local_parameters(), replaceSpeciesReferences(), and CEvaluationNode::type().

Referenced by createInitialAssignments().

1674 {
1675  // check the expression
1676  std::vector<SBMLIncompatibility> result;
1678  , dataModel
1679  , this->mSBMLLevel
1680  , this->mSBMLVersion
1681  , result
1682  , std::string("initial expression for object named \"" + modelEntity.getObjectName() + "\"").c_str()
1683  , true
1684  , &mInitialValueMap);
1685 
1686  // collect directly used functions
1687  if (result.empty())
1688  {
1689  std::set<std::string> directlyUsedFunctionNames;
1690  CSBMLExporter::findDirectlyUsedFunctions(modelEntity.getInitialExpressionPtr()->getRoot(), directlyUsedFunctionNames);
1691  std::set<CFunction*> usedFunctions = CSBMLExporter::createFunctionSetFromFunctionNames(directlyUsedFunctionNames, CCopasiRootContainer::getFunctionList());
1692 
1693 #if defined _MSC_VER && _MSC_VER < 1201 // 1200 Identifies Visual C++ 6.0
1694  {
1695  std::set<CFunction*>::const_iterator it = usedFunctions.begin();
1696  std::set<CFunction*>::const_iterator end = usedFunctions.end();
1697 
1698  for (; it != end; ++it)
1699  this->mUsedFunctions.insert(*it);
1700  }
1701 #else
1702  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
1703 #endif
1704 
1705  // create the actual initial assignment
1706  InitialAssignment* pInitialAssignment = this->mpSBMLDocument->getModel()->getInitialAssignment(modelEntity.getSBMLId());
1707 
1708  if (pInitialAssignment == NULL)
1709  {
1710  pInitialAssignment = this->mpSBMLDocument->getModel()->createInitialAssignment();
1711  pInitialAssignment->setSymbol(modelEntity.getSBMLId());
1712  }
1713 
1714  // set the math
1715  this->mHandledSBMLObjects.insert(pInitialAssignment);
1716  const CEvaluationNode* pOrigNode = modelEntity.getInitialExpressionPtr()->getRoot();
1717 
1719  {
1720  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 70, "initial assignment", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
1721  }
1722 
1723  // the next few lines replace references to species depending on whether
1724  // it is a reference to an amount or a reference to a concentration.
1725  // Other factors that influence this replacement are if the model
1726  // contains variable volumes or if the quantity units are set to CModel::number
1727  pOrigNode = this->replaceSpeciesReferences(pOrigNode, dataModel);
1728  assert(pOrigNode != NULL);
1729 
1730  // check if the rule is for an amount species
1731  // if this is the case, we have to multiply the expression by the volume
1732  // of the compartment the species is in
1733  // create the actual rule
1734  const CMetab* pMetab = dynamic_cast<const CMetab*>(&modelEntity);
1735 
1736  if (pMetab != NULL)
1737  {
1738  std::map<const CCopasiObject*, SBase*>::const_iterator pos = this->mCOPASI2SBMLMap.find(&modelEntity);
1739  assert(pos != this->mCOPASI2SBMLMap.end());
1740 
1741  if (dynamic_cast<const Species*>(pos->second)->getHasOnlySubstanceUnits() == true)
1742  {
1743  const CCompartment* pCompartment = pMetab->getCompartment();
1744 
1745  if (pCompartment->getDimensionality() != 0)
1746  {
1747  CEvaluationNode* pNode = CSBMLExporter::multiplyByObject(pOrigNode, pCompartment->getInitialValueReference());
1748  assert(pNode != NULL);
1749 
1750  if (pNode != NULL)
1751  {
1752  delete pOrigNode;
1753  pOrigNode = pNode;
1754  }
1755  }
1756  }
1757  }
1758 
1759  ASTNode* pNode = this->convertToASTNode(pOrigNode, dataModel);
1760  delete pOrigNode;
1761  // convert local parameters that are referenced in an expression to global
1762  // parameters
1763  this->replace_local_parameters(pNode, dataModel);
1764 
1765  if (pNode != NULL)
1766  {
1767  pInitialAssignment->setMath(pNode);
1768  delete pNode;
1769  }
1770  else
1771  {
1772  if (this->mIncompleteExport == true)
1773  {
1774  // remove the initial assignment from the SBML model
1775  unsigned int i = 0, iMax = this->mpSBMLDocument->getModel()->getNumInitialAssignments();
1776 
1777  while (i < iMax)
1778  {
1779  if (this->mpSBMLDocument->getModel()->getInitialAssignment(i)->getSymbol() == modelEntity.getSBMLId())
1780  {
1781  this->mpSBMLDocument->getModel()->getListOfInitialAssignments()->remove(i);
1782  break;
1783  }
1784 
1785  ++i;
1786  }
1787  }
1788  else
1789  {
1790  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "initial assignment", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
1791  }
1792  }
1793  }
1794  else
1795  {
1796  this->mIncompatibilities.insert(this->mIncompatibilities.end(), result.begin(), result.end());
1797 
1798  if (!this->mIncompleteExport)
1799  {
1800  this->outputIncompatibilities();
1801  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "initial assignment", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
1802  }
1803  }
1804 }
static void findDirectlyUsedFunctions(const CEvaluationNode *pRootNode, std::set< std::string > &result)
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
void replace_local_parameters(ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
const std::string & getSBMLId() const
static CEvaluationNode * multiplyByObject(const CEvaluationNode *pOrigNode, const CCopasiObject *pObject)
const std::string & getObjectName() const
unsigned C_INT32 getDimensionality() const
CCopasiObject * getInitialValueReference() const
const Type & getType() const
const std::string & getObjectType() const
bool mIncompleteExport
Definition: CSBMLExporter.h:66
Definition: CMetab.h:178
std::map< const std::string, Parameter * > mInitialValueMap
Definition: CSBMLExporter.h:79
static Type type(const Type &type)
#define MCSBML
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
static CFunctionDB * getFunctionList()
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
ASTNode * convertToASTNode(const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
static void isExpressionSBMLCompatible(const CEvaluationTree &expr, const CCopasiDataModel &dataModel, int sbmlLevel, int sbmlVersion, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription, bool initialExression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
CEvaluationNode * replaceSpeciesReferences(const CEvaluationNode *pOrigNode, const CCopasiDataModel &dataModel)
void outputIncompatibilities() const
std::set< SBase * > mHandledSBMLObjects
Definition: CSBMLExporter.h:62
static const std::set< CFunction * > createFunctionSetFromFunctionNames(const std::set< std::string > &names, CFunctionDB *pFunDB)
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
const CCompartment * getCompartment() const
Definition: CMetab.cpp:222
CEvaluationNode * getRoot()
const CExpression * getInitialExpressionPtr() const
void CSBMLExporter::createInitialAssignments ( CCopasiDataModel dataModel)
protected

Creates the initial assignments for the model.

Definition at line 1650 of file CSBMLExporter.cpp.

References createInitialAssignment(), and mInitialAssignmentVector.

Referenced by createSBMLDocument().

1651 {
1652  // make sure the mInitialAssignmentVector has been filled already
1653 
1654  // create the initial assignments
1655  size_t i, iMax = this->mInitialAssignmentVector.size();
1656  const CModelEntity* pME = NULL;
1657 
1658  for (i = 0; i < iMax; ++i)
1659  {
1660  pME = mInitialAssignmentVector[i];
1661  assert(pME != NULL);
1662 
1663  if (pME != NULL)
1664  {
1665  createInitialAssignment(*pME, dataModel);
1666  }
1667  }
1668 }
void createInitialAssignment(const CModelEntity &modelEntity, CCopasiDataModel &dataModel)
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
CEvaluationNode * CSBMLExporter::createKineticExpression ( CFunction pFun,
const std::vector< std::vector< std::string > > &  arguments 
)
protected

Creates an expression from a given node and a set of parameter mappings by replacing the function arguments with the parameters. static CEvaluationNode* createExpressionTree(const CEvaluationNode* const pNode, const std::map<std::string, std::string>& parameterMap, const CCopasiDataModel& dataModel); Creates an expression from a given function and a set of parameters by replacing the function arguments with the parameters. static CEvaluationNode* createExpressionTree(const CFunction* const pFun, const std::vector<std::vector<std::string> >& arguments, const CCopasiDataModel& dataModel); Create an expression that corresponds to a kinetic law. If the kinetic law was mass action, the expression is a mass action term , otherwise it is a function call.

Definition at line 4802 of file CSBMLExporter.cpp.

References CEvaluationNodeCall::addChild(), CEvaluationNodeObject::CN, createMassActionExpression(), fatalError, CEvaluationNodeCall::FUNCTION, CKeyFactory::get(), CCopasiObject::getCN(), CCopasiRootContainer::getKeyFactory(), CCopasiObject::getObjectName(), CEvaluationTree::getType(), CFunction::getVariables(), CFunction::isReversible(), CEvaluationTree::MassAction, mUsedFunctions, pResult, CFunctionParameters::size(), and TriTrue.

Referenced by createKineticLaw().

4803 {
4804  if (!pFun || pFun->getVariables().size() != arguments.size()) fatalError();
4805 
4807 
4808  if (pFun->getType() == CEvaluationTree::MassAction)
4809  {
4810  pResult = CSBMLExporter::createMassActionExpression(arguments, pFun->isReversible() == TriTrue);
4811  }
4812  else
4813  {
4815  this->mUsedFunctions.insert(pFun);
4816  size_t i, iMax = arguments.size();
4817  std::string cn;
4818 
4819  for (i = 0; i < iMax; ++i)
4820  {
4821  if (arguments[i].size() != 1) fatalError(); // we can't have arrays here.
4822 
4823  const CCopasiObject* pObject = CCopasiRootContainer::getKeyFactory()->get(arguments[i][0]);
4824 
4825  if (!pObject) fatalError();
4826 
4827  if (dynamic_cast<const CModel*>(pObject) != NULL)
4828  {
4829  cn = "<" + pObject->getCN() + ",Reference=Time>";
4830  }
4831  else if (dynamic_cast<const CCompartment*>(pObject) != NULL)
4832  {
4833  cn = "<" + pObject->getCN() + ",Reference=Volume>";
4834  }
4835  else if (dynamic_cast<const CMetab*>(pObject) != NULL)
4836  {
4837  cn = "<" + pObject->getCN() + ",Reference=Concentration>";
4838  }
4839  else if (dynamic_cast<const CModelValue*>(pObject) != NULL)
4840  {
4841  cn = "<" + pObject->getCN() + ",Reference=Value>";
4842  }
4843  else if (dynamic_cast<const CReaction*>(pObject) != NULL)
4844  {
4845  cn = "<" + pObject->getCN() + ",Reference=Flux>";
4846  }
4847  else if (dynamic_cast<const CCopasiParameter*>(pObject) != NULL)
4848  {
4849  // local parameter of a reaction
4850  // must set the node content to the SBML id if the parameter
4851  cn = "<" + pObject->getCN() + ">";
4852  }
4853  else
4854  {
4855  cn = "<" + pObject->getCN() + ">";
4856  }
4857 
4858  pFunctionCall->addChild(new CEvaluationNodeObject(CEvaluationNodeObject::CN, cn));
4859  }
4860 
4861  pResult = pFunctionCall;
4862  }
4863 
4864  return pResult;
4865 }
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
virtual CCopasiObjectName getCN() const
const std::string & getObjectName() const
CCopasiObject * get(const std::string &key)
#define fatalError()
const CEvaluationTree::Type & getType() const
const TriLogic & isReversible() const
Definition: CFunction.cpp:145
const CArrayAnnotation * pResult
static CKeyFactory * getKeyFactory()
static CEvaluationNode * createMassActionExpression(const std::vector< std::vector< std::string > > &arguments, bool isReversible)
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
CFunctionParameters & getVariables()
Definition: CFunction.cpp:148
KineticLaw * CSBMLExporter::createKineticLaw ( CReaction reaction,
CCopasiDataModel dataModel,
unsigned int  level,
unsigned int  version 
)
protected

Create the kinetic law for the given reaction. On failure NULL is returned.

Definition at line 4584 of file CSBMLExporter.cpp.

References convertToASTNode(), createKineticExpression(), fatalError, CKeyFactory::get(), CReaction::getChemEq(), CCopasiParameter::getCN(), CReaction::getCompartmentNumber(), CCompartment::getDimensionality(), CReaction::getFunction(), CReaction::getFunctionParameters(), CCopasiRootContainer::getKeyFactory(), CCopasiObject::getObjectName(), CReaction::getParameterMapping(), CReaction::getParameterMappings(), CReaction::getParameterValue(), CChemEq::getProducts(), CModelEntity::getSBMLId(), CChemEq::getSubstrates(), CFunctionParameter::getUsage(), isDividedByVolume(), CReaction::isLocalParameter(), CFunction::isReversible(), mParameterReplacementMap, mpSBMLDocument, mSBMLLevel, CFunctionParameter::PARAMETER, replaceSpeciesReferences(), restore_local_parameters(), CFunctionParameters::size(), CCopasiVector< T >::size(), TriUnspecified, and CFunctionParameter::VARIABLE.

Referenced by createReaction().

4585 {
4586  KineticLaw* pKLaw = NULL;
4587 
4588  if (!pKLaw)
4589  {
4590  /* create a new KineticLaw */
4591  pKLaw = new KineticLaw(level, version);
4592  }
4593 
4594  // create the local parameters
4595  size_t i, iMax = reaction.getFunctionParameters().size();
4596 
4597  for (i = 0; i < iMax; ++i)
4598  {
4599  const CFunctionParameter* pPara = reaction.getFunctionParameters()[i];
4600  // if the reaction calls a general function, all call parameters have a usage of VARIABLE
4601  // So local parameters will also have a usage of VARIABLE instead of PARAMETER
4602 
4603  if (pPara->getUsage() == CFunctionParameter::PARAMETER ||
4604  (reaction.getFunction() != NULL &&
4605  reaction.getFunction()->isReversible() == TriUnspecified &&
4607  {
4608  // only create a parameter if it is a local parameter,
4609  // and if it is not in the replacement map
4610  // otherwise the parameter already has been created
4611  if (reaction.isLocalParameter(i))
4612  {
4613  std::vector<std::string> v = reaction.getParameterMapping(pPara->getObjectName());
4614  assert(v.size() == 1);
4615  CCopasiObject* pTmpObject = CCopasiRootContainer::getKeyFactory()->get(v[0]);
4616  assert(pTmpObject != NULL);
4617  CCopasiParameter* pLocalParameter = dynamic_cast<CCopasiParameter*>(pTmpObject);
4618  assert(pLocalParameter != NULL);
4619 
4620  if (this->mParameterReplacementMap.find(pLocalParameter->getCN()) == this->mParameterReplacementMap.end())
4621  {
4622  // starting with SBML Level 3, the parameters of a kinetic law are expressed in
4623  // libsbml 4.1 does not handle this in a nice way,
4624  // so way have to distinguish between the levels we export
4625  // Actually here we could probably have gotten away with the old code, but
4626  // better safe than sorry
4627  Parameter* pSBMLPara = NULL;
4628 #if LIBSBML_VERSION >= 40100
4629 
4630  if (this->mSBMLLevel > 2)
4631  {
4632  pSBMLPara = pKLaw->createLocalParameter();
4633  }
4634  else
4635  {
4636 #endif // LIBSBML_VERSION
4637  pSBMLPara = pKLaw->createParameter();
4638 #if LIBSBML_VERSION >= 40100
4639  }
4640 
4641  pSBMLPara->setId(pPara->getObjectName().c_str());
4642 #endif // LIBSBML_VERSION
4643 
4644  // don't call setName on level 1 objects because this will also
4645  // change the id
4646  if (this->mpSBMLDocument->getLevel() > 1)
4647  {
4648  pSBMLPara->setName(pPara->getObjectName().c_str());
4649  }
4650 
4651  double value = reaction.getParameterValue(pPara->getObjectName());
4652 
4653  // if the value is NaN, leave the parameter value unset.
4654  if (!isnan(value))
4655  {
4656  pSBMLPara->setValue(value);
4657  }
4658  }
4659  }
4660  }
4661  }
4662 
4663  // the next few lines replace references to species depending on whether
4664  // it is a reference to an amount or a reference to a concentration.
4665  // Other factors that influence this replacement are if the model
4666  // contains variable volumes or if the quantity units are set to CModel::number
4667  CEvaluationNode* pExpression = CSBMLExporter::createKineticExpression(const_cast<CFunction*>(reaction.getFunction()), reaction.getParameterMappings());
4668 
4669  if (pExpression == NULL)
4670  {
4671  delete pKLaw;
4672  pKLaw = NULL;
4673  }
4674  else
4675  {
4676  /*
4677  ** If the reaction takes place in a single compartment, the rate law has
4678  ** to be converted from concentration/time to substance/time by
4679  ** multiplying the rate law with the volume of the compartment.
4680  */
4681  CEvaluationNode* pOrigNode = this->replaceSpeciesReferences(pExpression, dataModel);
4682  delete pExpression;
4683  assert(pOrigNode != NULL);
4684  ASTNode* pNode = this->convertToASTNode(pOrigNode, dataModel);
4685  // since toAST in CEvaluationNodeObject sets the CN of local parameters
4686  // as the name of the node, we have to go and replace all node names
4687  // that have a common name that is the CN of a local parameter
4688  this->restore_local_parameters(pNode, dataModel);
4689  delete pOrigNode;
4690  assert(pNode != NULL);
4691 
4692  if (reaction.getCompartmentNumber() == 1)
4693  {
4694  const CCompartment& compartment = (reaction.getChemEq().getSubstrates().size() != 0) ? (*reaction.getChemEq().getSubstrates()[0]->getMetabolite()->getCompartment()) : (*reaction.getChemEq().getProducts()[0]->getMetabolite()->getCompartment());
4695 
4696  if (compartment.getDimensionality() != 0)
4697  {
4698  // check if the importer has added a division by the volume
4699  // if so remove it instead of multiplying again
4700  ASTNode* pTNode = CSBMLExporter::isDividedByVolume(pNode, compartment.getSBMLId());
4701 
4702  if (pTNode)
4703  {
4704  if (pTNode->getNumChildren() == 0)
4705  {
4706  fatalError();
4707  }
4708 
4709  if (pTNode->getNumChildren() == 1)
4710  {
4711  ASTNode* pTmp = static_cast<ConverterASTNode*>(pTNode)->removeChild(0);
4712  delete pTNode;
4713  pTNode = pTmp;
4714  }
4715 
4716  delete pNode;
4717  pNode = pTNode;
4718  }
4719  else
4720  {
4721  pTNode = new ASTNode(AST_TIMES);
4722  ASTNode* pVNode = new ASTNode(AST_NAME);
4723  pVNode->setName(compartment.getSBMLId().c_str());
4724  pTNode->addChild(pVNode);
4725  pTNode->addChild(pNode);
4726  pNode = pTNode;
4727  }
4728  }
4729  }
4730 
4731  pKLaw->setMath(pNode);
4732  delete pNode;
4733  }
4734 
4735  return pKLaw;
4736 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
const std::string & getObjectName() const
std::map< std::string, Parameter * > mParameterReplacementMap
Definition: CSBMLExporter.h:75
unsigned C_INT32 getDimensionality() const
virtual size_t size() const
CCopasiObject * get(const std::string &key)
#define fatalError()
bool isLocalParameter(const size_t &index) const
Definition: CReaction.cpp:449
const CCopasiVector< CChemEqElement > & getProducts() const
Definition: CChemEq.cpp:63
const CFunction * getFunction() const
Definition: CReaction.cpp:252
const CFunctionParameters & getFunctionParameters() const
Definition: CReaction.cpp:576
const TriLogic & isReversible() const
Definition: CFunction.cpp:145
static ASTNode * isDividedByVolume(const ASTNode *pRootNode, const std::string &compartmentId)
const CCopasiVector< CChemEqElement > & getSubstrates() const
Definition: CChemEq.cpp:60
virtual CCopasiObjectName getCN() const
static CKeyFactory * getKeyFactory()
ASTNode * convertToASTNode(const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
void restore_local_parameters(ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
size_t getCompartmentNumber() const
Definition: CReaction.cpp:873
CEvaluationNode * replaceSpeciesReferences(const CEvaluationNode *pOrigNode, const CCopasiDataModel &dataModel)
CEvaluationNode * createKineticExpression(CFunction *pFun, const std::vector< std::vector< std::string > > &arguments)
const std::vector< std::vector< std::string > > & getParameterMappings() const
Definition: CReaction.h:285
const CChemEq & getChemEq() const
Definition: CReaction.cpp:223
const C_FLOAT64 & getParameterValue(const std::string &parameterName) const
Definition: CReaction.cpp:326
const std::vector< std::string > & getParameterMapping(const size_t &index) const
Definition: CReaction.cpp:432
void CSBMLExporter::createLengthUnit ( const CCopasiDataModel dataModel)
protected

Creates the volume unit for the SBML model.

Creates the length unit for the SBML model.

Definition at line 689 of file CSBMLExporter.cpp.

References SBMLImporter::areSBMLUnitDefinitionsIdentical(), CModel::cm, CModel::dimensionlessLength, CModel::dm, CCopasiMessage::EXCEPTION, CModel::fm, CModel::getLengthUnitEnum(), CCopasiDataModel::getModel(), INIT_DEFAULTS, CModel::m, CModel::microm, CModel::mm, mpSBMLDocument, mSBMLLevel, mSBMLVersion, CModel::nm, and CModel::pm.

Referenced by createUnits().

690 {
691  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
692 
693  UnitDefinition uDef(this->mSBMLLevel, this->mSBMLVersion);
694  uDef.setName("length");
695  uDef.setId("length");
696  Unit unit(this->mSBMLLevel, this->mSBMLVersion);
697  INIT_DEFAULTS(unit);
698 
699  switch (dataModel.getModel()->getLengthUnitEnum())
700  {
701  case CModel::m:
702  unit.setKind(UNIT_KIND_METRE);
703  unit.setExponent(1);
704  unit.setScale(0);
705  break;
706 
707  case CModel::dm:
708  unit.setKind(UNIT_KIND_METRE);
709  unit.setExponent(1);
710  unit.setScale(-1);
711  break;
712 
713  case CModel::cm:
714  unit.setKind(UNIT_KIND_METRE);
715  unit.setExponent(1);
716  unit.setScale(-2);
717  break;
718 
719  case CModel::mm:
720  unit.setKind(UNIT_KIND_METRE);
721  unit.setExponent(1);
722  unit.setScale(-3);
723  break;
724 
725  case CModel::microm:
726  unit.setKind(UNIT_KIND_METRE);
727  unit.setExponent(1);
728  unit.setScale(-6);
729  break;
730 
731  case CModel::nm:
732  unit.setKind(UNIT_KIND_METRE);
733  unit.setExponent(1);
734  unit.setScale(-9);
735  break;
736 
737  case CModel::pm:
738  unit.setKind(UNIT_KIND_METRE);
739  unit.setExponent(1);
740  unit.setScale(-12);
741  break;
742 
743  case CModel::fm:
744  unit.setKind(UNIT_KIND_METRE);
745  unit.setExponent(1);
746  unit.setScale(-15);
747  break;
748 
750  unit.setKind(UNIT_KIND_DIMENSIONLESS);
751  unit.setExponent(1);
752  unit.setScale(0);
753  break;
754 
755  default:
756  CCopasiMessage(CCopasiMessage::EXCEPTION, "SBMLExporter Error: Unknown copasi length unit.");
757  break;
758  }
759 
760  unit.setMultiplier(1.0);
761  uDef.addUnit(&unit);
762  Model* pSBMLModel = this->mpSBMLDocument->getModel();
763  UnitDefinition* pUdef = pSBMLModel->getUnitDefinition("length");
764 
765  if (pUdef != NULL)
766  {
767  // check if it is the same unit as the existing one if there is one
768  // if yes, return, else replace the existing one
770  {
771  (*pUdef) = uDef;
772  }
773  }
774  else
775  {
776  // only add it if it is not the default unit definition anyway
777  if (this->mSBMLLevel > 2 || unit.getKind() != UNIT_KIND_METRE || unit.getScale() != 0 || unit.getExponent() != 1 || unit.getMultiplier() != 1.0)
778  {
779  // set the unit definition
780  pSBMLModel->addUnitDefinition(&uDef);
781  }
782  }
783 
784 // if we write an SBML L3 document, we have to explicitely set the units on the model
785 #if LIBSBML_VERSION >= 40100
786 
787  if (this->mSBMLLevel > 2)
788  {
789  pSBMLModel->setLengthUnits(uDef.getId());
790  }
791 
792 #endif // LIBSBML_VERSION
793 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
CModel::LengthUnit getLengthUnitEnum() const
Definition: CModel.cpp:2220
#define INIT_DEFAULTS(element)
static bool areSBMLUnitDefinitionsIdentical(const UnitDefinition *pUdef1, const UnitDefinition *pUdef2)
CEvaluationNode * CSBMLExporter::createMassActionExpression ( const std::vector< std::vector< std::string > > &  arguments,
bool  isReversible 
)
staticprotected

This method creates the CEvaluationNode based tree for a reversible or irreversible Mass Action call. The first parameter contains the arguments from the COPASI reaction. The second argument determines whether it is reversible or irreversible mass action.

Definition at line 5907 of file CSBMLExporter.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNodeObject::CN, CEvaluationNodeNumber::DOUBLE, CKeyFactory::get(), CCopasiObject::getCN(), CCopasiRootContainer::getKeyFactory(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNodeOperator::POWER, and pResult.

Referenced by createKineticExpression().

5908 {
5909  assert((isReversible && arguments.size() == 4) || arguments.size() == 2);
5910  assert(arguments[0].size() == 1 && arguments[1].size() > 0);
5911  // create a multiplication of all items in arguments[1] and multiply that
5912  // with item arguments[0][0]
5913  std::set<std::string> finishedElements;
5914  std::vector<CEvaluationNode*> multiplicants;
5915  const CCopasiObject* pObject = CCopasiRootContainer::getKeyFactory()->get(arguments[0][0]);
5916  assert(pObject != NULL);
5917  multiplicants.push_back(new CEvaluationNodeObject(CEvaluationNodeObject::CN, "<" + pObject->getCN() + ",Reference=Value>"));
5918  std::vector<std::string>::const_iterator it = arguments[1].begin(), endit = arguments[1].end();
5919 
5920  while (it != endit)
5921  {
5922  if (finishedElements.find(*it) == finishedElements.end())
5923  {
5924 #ifdef __SUNPRO_CC
5925  // replaced count call with "old" count call
5926  // to compile on Sun Compiler
5927  unsigned int num = 0;
5928  std::count(arguments[1].begin(), arguments[1].end(), *it, num);
5929 #else
5930  size_t num = std::count(arguments[1].begin(), arguments[1].end(), *it);
5931 #endif // __SUNPRO_CC
5932  assert(num != 0);
5933  finishedElements.insert(*it);
5934  pObject = CCopasiRootContainer::getKeyFactory()->get(*it);
5935  assert(pObject != NULL);
5936 
5937  if (num == 1)
5938  {
5939  multiplicants.push_back(new CEvaluationNodeObject(CEvaluationNodeObject::CN, "<" + pObject->getCN() + ",Reference=Concentration>"));
5940  }
5941  else
5942  {
5943  std::ostringstream os;
5944  os << num;
5946  pOperator->addChild(new CEvaluationNodeObject(CEvaluationNodeObject::CN, "<" + pObject->getCN() + ",Reference=Concentration>"));
5948  multiplicants.push_back(pOperator);
5949  }
5950  }
5951 
5952  ++it;
5953  }
5954 
5955  std::vector<CEvaluationNode*>::reverse_iterator rIt = multiplicants.rbegin(), rEndit = multiplicants.rend();
5956  CEvaluationNode* pResult = *rIt;
5957  ++rIt;
5958  CEvaluationNode* pTmpNode = NULL;
5959 
5960  if (rIt != rEndit)
5961  {
5962  --rEndit;
5963 
5964  while (rIt != rEndit)
5965  {
5967  pTmpNode->addChild(*rIt);
5968  pTmpNode->addChild(pResult);
5969  pResult = pTmpNode;
5970  ++rIt;
5971  }
5972  }
5973 
5975  pTmpNode->addChild(*rIt);
5976  pTmpNode->addChild(pResult);
5977  pResult = pTmpNode;
5978 
5979  if (isReversible)
5980  {
5981  std::vector<std::vector<std::string> > tmpV;
5982  tmpV.push_back(arguments[2]);
5983  tmpV.push_back(arguments[3]);
5985  pTmpNode->addChild(pResult);
5986  pTmpNode->addChild(CSBMLExporter::createMassActionExpression(tmpV, false));
5987  pResult = pTmpNode;
5988  }
5989 
5990  return pResult;
5991 }
virtual CCopasiObjectName getCN() const
CCopasiObject * get(const std::string &key)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
static CKeyFactory * getKeyFactory()
static CEvaluationNode * createMassActionExpression(const std::vector< std::vector< std::string > > &arguments, bool isReversible)
void CSBMLExporter::createMetabolite ( CMetab metab)
protected

Creates the species for the given COPASI metabolite.

Definition at line 1105 of file CSBMLExporter.cpp.

References CModelEntity::ASSIGNMENT, createUniqueId(), CModelEntity::FIXED, CMetab::getCompartment(), CMetab::getInitialConcentration(), CModelEntity::getInitialExpression(), CModelEntity::getInitialValue(), CMetab::getObjectDisplayName(), CCopasiObject::getObjectName(), CModelEntity::getSBMLId(), CModelEntity::getStatus(), INIT_DEFAULTS, mAssignmentVector, mCOPASI2SBMLMap, mHandledSBMLObjects, mIdMap, mInitialAssignmentVector, mMetaIdMap, mODEVector, mpSBMLDocument, mSBMLLevel, mSBMLVersion, mSpatialSizeUnitsSpecies, mVariableVolumes, CModelEntity::ODE, CModelEntity::REACTIONS, removeInitialAssignment(), removeRule(), CModelEntity::setSBMLId(), setSBMLNotes(), and updateMIRIAMAnnotation().

Referenced by createMetabolites().

1106 {
1107  Species* pSBMLSpecies = NULL;
1108  std::string sbmlId = metab.getSBMLId();
1109 
1110  if (!sbmlId.empty())
1111  {
1112  pSBMLSpecies = this->mpSBMLDocument->getModel()->getSpecies(sbmlId);
1113 
1114  if (pSBMLSpecies == NULL)
1115  {
1116  pSBMLSpecies = this->mpSBMLDocument->getModel()->createSpecies();
1117  this->mCOPASI2SBMLMap[&metab] = pSBMLSpecies;
1118  pSBMLSpecies->setId(sbmlId);
1119  }
1120  else
1121  {
1122 #if LIBSBML_VERSION >= 40100
1123 
1124  if (this->mSBMLLevel > 2)
1125  {
1126  pSBMLSpecies->unsetConversionFactor();
1127  // we have to remove the conversionFactor because on import we multiplied the stoichiometries
1128  // with this factor
1129  }
1130 
1131 #endif // LIBSBML_VERSION
1132 
1133  // clear the spatialSizeUnits attribute if there is any
1134  if (this->mSBMLLevel > 2 || (this->mSBMLLevel == 2 && this->mSBMLVersion >= 3))
1135  {
1136  if (pSBMLSpecies->isSetSpatialSizeUnits())
1137  {
1138  pSBMLSpecies->unsetSpatialSizeUnits();
1139  this->mSpatialSizeUnitsSpecies.insert(pSBMLSpecies->getId());
1140  }
1141  }
1142  }
1143  }
1144  else
1145  {
1146  pSBMLSpecies = this->mpSBMLDocument->getModel()->createSpecies();
1147  this->mCOPASI2SBMLMap[&metab] = pSBMLSpecies;
1148  sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, metab.getObjectDisplayName(), false);
1149  metab.setSBMLId(sbmlId);
1150  pSBMLSpecies->setId(sbmlId);
1151  }
1152 
1153  INIT_DEFAULTS((*pSBMLSpecies));
1154 
1155  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, pSBMLSpecies));
1156  this->mHandledSBMLObjects.insert(pSBMLSpecies);
1157 
1158  // don't call setName on level 1 objects because this will also
1159  // change the id
1160  if (this->mpSBMLDocument->getLevel() > 1)
1161  {
1162  pSBMLSpecies->setName(metab.getObjectName().c_str());
1163  }
1164 
1165  //const Compartment* pSBMLCompartment = dynamic_cast<const Compartment*>(this->mCOPASI2SBMLMap[const_cast<CCompartment*>(metab.getCompartment())]);
1166  const Compartment* pSBMLCompartment = this->mpSBMLDocument->getModel()->getCompartment(metab.getCompartment()->getSBMLId());
1167  assert(pSBMLCompartment);
1168  pSBMLSpecies->setCompartment(pSBMLCompartment->getId());
1169 
1170  if (this->mVariableVolumes == true)
1171  {
1172  pSBMLSpecies->setHasOnlySubstanceUnits(true);
1173  }
1174 
1175  double value = metab.getInitialConcentration();
1176 
1177  // if the value is NaN, unset the initial amount
1178  if (!isnan(value))
1179  {
1180  // if we set the concentration on a species that had the amount
1181  // set, the meaning of the model is different when the user changed
1182  // to size of the corresponding compartment
1183  // So if the amount had been set, we try to keep this.
1184  // we also have to set the initial amount if the model has variable
1185  // volumes since those models export all species with the
1186  // hasOnlySubstanceUnits flag set to true
1187  //
1188  // libsbml 4 does not set the initial concentration on a species any more
1189  // so we also have to set the initial amount
1190  if (pSBMLSpecies->isSetInitialAmount() || this->mVariableVolumes == true || pSBMLSpecies->getLevel() == 1)
1191  {
1192  pSBMLSpecies->setInitialAmount(value * metab.getCompartment()->getInitialValue());
1193  }
1194  else
1195  {
1196  pSBMLSpecies->setInitialConcentration(value);
1197  }
1198  }
1199  else
1200  {
1201  pSBMLSpecies->unsetInitialConcentration();
1202  pSBMLSpecies->unsetInitialAmount();
1203  }
1204 
1205  CModelEntity::Status status = metab.getStatus();
1206 
1207  // a species can either have an assignment or an initial assignment but not
1208  // both
1209  if (status == CModelEntity::ASSIGNMENT)
1210  {
1211  this->mAssignmentVector.push_back(&metab);
1212  pSBMLSpecies->setConstant(false);
1213  pSBMLSpecies->setBoundaryCondition(true);
1214  removeInitialAssignment(pSBMLSpecies->getId());
1215  }
1216  else if (status == CModelEntity::ODE)
1217  {
1218  this->mODEVector.push_back(&metab);
1219  pSBMLSpecies->setConstant(false);
1220  pSBMLSpecies->setBoundaryCondition(true);
1221 
1222  if (metab.getInitialExpression() != "")
1223  {
1224  this->mInitialAssignmentVector.push_back(&metab);
1225  }
1226  else
1227  {
1228  removeInitialAssignment(pSBMLSpecies->getId());
1229  }
1230  }
1231  else if (status == CModelEntity::FIXED)
1232  {
1233  // do this explicitly since we might handle an existing object from an
1234  // earlier import that had it attribute set already
1235  if (this->mSBMLLevel != 1)
1236  {
1237  pSBMLSpecies->setConstant(true);
1238  }
1239  else
1240  {
1241  // Level 1 doesn't have the constant attribute and libSBML 3.2.0 does
1242  // not drop it automatically
1243  pSBMLSpecies->setConstant(false);
1244  }
1245 
1246  pSBMLSpecies->setBoundaryCondition(true);
1247  removeRule(pSBMLSpecies->getId());
1248 
1249  // fill initial assignment set
1250  if (metab.getInitialExpression() != "")
1251  {
1252  this->mInitialAssignmentVector.push_back(&metab);
1253  }
1254  else
1255  {
1256  removeInitialAssignment(pSBMLSpecies->getId());
1257  }
1258  }
1259  else if (status == CModelEntity::REACTIONS)
1260  {
1261  pSBMLSpecies->setConstant(false);
1262  pSBMLSpecies->setBoundaryCondition(false);
1263 
1264  if (metab.getInitialExpression() != "")
1265  {
1266  this->mInitialAssignmentVector.push_back(&metab);
1267  }
1268  }
1269 
1270  if (pSBMLSpecies != NULL)
1271  {
1272  CSBMLExporter::setSBMLNotes(pSBMLSpecies, &metab);
1273  }
1274 
1275  if (pSBMLSpecies != NULL && mSBMLLevel == 3)
1276  {
1277  // for l3 the unit needs to be set explicitly to substance,
1278  pSBMLSpecies->setSubstanceUnits("substance");
1279  }
1280 
1281  CSBMLExporter::updateMIRIAMAnnotation(&metab, pSBMLSpecies, this->mMetaIdMap);
1282 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
const std::string & getObjectName() const
const C_FLOAT64 & getInitialConcentration() const
Definition: CMetab.cpp:220
virtual std::string getObjectDisplayName(bool regular=true, bool richtext=false) const
Definition: CMetab.cpp:974
std::vector< CModelEntity * > mAssignmentVector
Definition: CSBMLExporter.h:58
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
std::set< std::string > mSpatialSizeUnitsSpecies
Definition: CSBMLExporter.h:76
const C_FLOAT64 & getInitialValue() const
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
std::string getInitialExpression() const
void removeInitialAssignment(const std::string &sbmlId)
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
#define INIT_DEFAULTS(element)
std::set< SBase * > mHandledSBMLObjects
Definition: CSBMLExporter.h:62
const CModelEntity::Status & getStatus() const
bool mVariableVolumes
Definition: CSBMLExporter.h:67
void setSBMLId(const std::string &id)
const CCompartment * getCompartment() const
Definition: CMetab.cpp:222
void removeRule(const std::string &sbmlId)
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
void CSBMLExporter::createMetabolites ( CCopasiDataModel dataModel)
protected

Creates the compartments for the model.

Definition at line 1068 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), check_for_spatial_size_units(), createMetabolite(), CCopasiVector< T >::end(), CModel::getMetabolites(), CCopasiDataModel::getModel(), MCSBML, mIncompatibilities, mpSBMLDocument, mSBMLLevel, mSBMLVersion, mSpatialSizeUnitsSpecies, and CCopasiMessage::WARNING.

Referenced by createSBMLDocument().

1069 {
1070  // make sure the SBML Document already exists and that it has a Model set
1071  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
1072 
1073  if (this->mSBMLLevel > 2 || (this->mSBMLLevel == 2 && this->mSBMLVersion >= 3))
1074  {
1076  }
1077 
1078  CCopasiVector<CMetab>::const_iterator it = dataModel.getModel()->getMetabolites().begin(), endit = dataModel.getModel()->getMetabolites().end();
1079  this->mSpatialSizeUnitsSpecies.clear();
1080 
1081  while (it != endit)
1082  {
1083  createMetabolite(**it);
1084  ++it;
1085  }
1086 
1087  if (!this->mSpatialSizeUnitsSpecies.empty())
1088  {
1089  std::ostringstream os;
1090  std::set<std::string>::const_iterator sit = this->mSpatialSizeUnitsSpecies.begin(), sendit = this->mSpatialSizeUnitsSpecies.end();
1091 
1092  while (sit != sendit)
1093  {
1094  os << *sit << ", ";
1095  ++sit;
1096  }
1097 
1098  CCopasiMessage(CCopasiMessage::WARNING, MCSBML + 84, os.str().substr(0, os.str().size() - 2).c_str());
1099  }
1100 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const CCopasiVector< CMetab > & getMetabolites() const
Definition: CModel.cpp:1051
void createMetabolite(CMetab &metab)
iterator begin()
std::set< std::string > mSpatialSizeUnitsSpecies
Definition: CSBMLExporter.h:76
#define MCSBML
iterator end()
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
static void check_for_spatial_size_units(const CCopasiDataModel &dataModel, std::vector< SBMLIncompatibility > &result)
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
void CSBMLExporter::createParameter ( CModelValue modelValue)
protected

Creates the parameter for the given COPASI parameter.

Definition at line 1304 of file CSBMLExporter.cpp.

References CModelEntity::ASSIGNMENT, createUniqueId(), CModelEntity::getInitialExpression(), CModelEntity::getInitialValue(), CCopasiObject::getObjectName(), CModelEntity::getSBMLId(), CModelEntity::getStatus(), INIT_DEFAULTS, mAssignmentVector, mCOPASI2SBMLMap, mHandledSBMLObjects, mIdMap, mInitialAssignmentVector, mMetaIdMap, mODEVector, mpSBMLDocument, mSBMLLevel, CModelEntity::ODE, removeInitialAssignment(), removeRule(), CModelEntity::setSBMLId(), setSBMLNotes(), and updateMIRIAMAnnotation().

Referenced by createParameters().

1305 {
1306  Parameter* pParameter = NULL;
1307  std::string sbmlId = modelValue.getSBMLId();
1308 
1309  if (!sbmlId.empty())
1310  {
1311  pParameter = this->mpSBMLDocument->getModel()->getParameter(sbmlId);
1312 
1313  if (pParameter == NULL)
1314  {
1315  pParameter = this->mpSBMLDocument->getModel()->createParameter();
1316  this->mCOPASI2SBMLMap[&modelValue] = pParameter;
1317  pParameter->setId(sbmlId);
1318  }
1319  }
1320  else
1321  {
1322  pParameter = this->mpSBMLDocument->getModel()->createParameter();
1323  this->mCOPASI2SBMLMap[&modelValue] = pParameter;
1324  sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, modelValue.getObjectName(), false);
1325  modelValue.setSBMLId(sbmlId);
1326  pParameter->setId(sbmlId);
1327  }
1328 
1329  INIT_DEFAULTS((*pParameter));
1330 
1331  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, pParameter));
1332  this->mHandledSBMLObjects.insert(pParameter);
1333 
1334  // don't call setName on level 1 objects because this will also
1335  // change the id
1336  if (this->mpSBMLDocument->getLevel() > 1)
1337  {
1338  pParameter->setName(modelValue.getObjectName());
1339  }
1340 
1341  double value = modelValue.getInitialValue();
1342 
1343  // if the value is NaN, unset the parameters value
1344  if (!isnan(value))
1345  {
1346  pParameter->setValue(value);
1347  }
1348  else
1349  {
1350  pParameter->unsetValue();
1351  }
1352 
1353  // fill assignment set
1354  // a parameter can either have an assignment or an initial assignment but not
1355  // both
1356  CModelEntity::Status status = modelValue.getStatus();
1357 
1358  if (status == CModelEntity::ASSIGNMENT)
1359  {
1360  this->mAssignmentVector.push_back(&modelValue);
1361  pParameter->setConstant(false);
1362  removeInitialAssignment(pParameter->getId());
1363  }
1364  else if (status == CModelEntity::ODE)
1365  {
1366  this->mODEVector.push_back(&modelValue);
1367  pParameter->setConstant(false);
1368 
1369  if (modelValue.getInitialExpression() != "")
1370  {
1371  this->mInitialAssignmentVector.push_back(&modelValue);
1372  }
1373  else
1374  {
1375  removeInitialAssignment(pParameter->getId());
1376  }
1377  }
1378  else
1379  {
1380  // do this explicitly since we might handle an existing object from an
1381  // earlier import that had it attribute set already
1382  if (this->mSBMLLevel != 1)
1383  {
1384  pParameter->setConstant(true);
1385  }
1386  else
1387  {
1388  // Level 1 does not have a constant flag
1389  // and libsbml does not drop it automatically
1390  pParameter->setConstant(false);
1391  }
1392 
1393  // fill initial assignment set
1394  removeRule(pParameter->getId());
1395 
1396  if (modelValue.getInitialExpression() != "")
1397  {
1398  this->mInitialAssignmentVector.push_back(&modelValue);
1399  }
1400  else
1401  {
1402  removeInitialAssignment(pParameter->getId());
1403  }
1404  }
1405 
1406  if (pParameter != NULL)
1407  {
1408  CSBMLExporter::setSBMLNotes(pParameter, &modelValue);
1409  }
1410 
1411  CSBMLExporter::updateMIRIAMAnnotation(&modelValue, pParameter, this->mMetaIdMap);
1412 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
const std::string & getObjectName() const
std::vector< CModelEntity * > mAssignmentVector
Definition: CSBMLExporter.h:58
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
const C_FLOAT64 & getInitialValue() const
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
std::string getInitialExpression() const
void removeInitialAssignment(const std::string &sbmlId)
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
#define INIT_DEFAULTS(element)
std::set< SBase * > mHandledSBMLObjects
Definition: CSBMLExporter.h:62
const CModelEntity::Status & getStatus() const
void setSBMLId(const std::string &id)
void removeRule(const std::string &sbmlId)
std::vector< CModelEntity * > mInitialAssignmentVector
Definition: CSBMLExporter.h:60
void CSBMLExporter::createParameters ( CCopasiDataModel dataModel)
protected

Creates the parameters for the model.

Definition at line 1287 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), createParameter(), CCopasiVector< T >::end(), CCopasiDataModel::getModel(), CModel::getModelValues(), and mpSBMLDocument.

Referenced by createSBMLDocument().

1288 {
1289  // make sure the SBML Document already exists and that it has a Model set
1290  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
1291 
1293 
1294  while (it != endit)
1295  {
1296  createParameter(**it);
1297  ++it;
1298  }
1299 }
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const CCopasiVectorN< CModelValue > & getModelValues() const
Definition: CModel.cpp:1060
iterator begin()
iterator end()
void createParameter(CModelValue &parameter)
void CSBMLExporter::createReaction ( CReaction reaction,
CCopasiDataModel dataModel 
)
protected

Creates the reaction for the given COPASI reaction.

Definition at line 1434 of file CSBMLExporter.cpp.

References createKineticLaw(), createUniqueId(), CCopasiMessage::EXCEPTION, CReaction::getChemEq(), CReaction::getFunction(), CChemEqElement::getMetabolite(), CChemEq::getModifiers(), CChemEqElement::getMultiplicity(), CCopasiObject::getObjectName(), CChemEq::getProducts(), CModelEntity::getSBMLId(), CReaction::getSBMLId(), CChemEq::getSubstrates(), CCopasiRootContainer::getUndefinedFunction(), INIT_DEFAULTS, CReaction::isReversible(), mCOPASI2SBMLMap, MCSBML, mHandledSBMLObjects, mIdMap, mIncompleteExport, mMetaIdMap, mpSBMLDocument, mSBMLLevel, CReaction::setSBMLId(), setSBMLNotes(), CCopasiVector< T >::size(), and updateMIRIAMAnnotation().

Referenced by createReactions().

1435 {
1436  // make sure the mCOPASI2SBMLMap is already updated
1437  Reaction* pSBMLReaction = NULL;
1438 
1439  // if the reaction has nothing set but the name, we don't do anything
1440  // This is mandated since SBML Level 2 Version 2. A reactions has to have either
1441  // a substrate or a product.
1442  if (reaction.getChemEq().getSubstrates().size() == 0 &&
1443  reaction.getChemEq().getProducts().size() == 0) return;
1444 
1445  std::string sbmlId = reaction.getSBMLId();
1446 
1447  if (!sbmlId.empty())
1448  {
1449  pSBMLReaction = this->mpSBMLDocument->getModel()->getReaction(sbmlId);
1450 
1451  if (pSBMLReaction == NULL)
1452  {
1453  /* create a new reaction object */
1454  pSBMLReaction = this->mpSBMLDocument->getModel()->createReaction();
1455  mCOPASI2SBMLMap[&reaction] = pSBMLReaction;
1456  pSBMLReaction->setId(sbmlId);
1457  }
1458 
1459  // maybe this id was assigned by assignSBMLIdstoReactions and there is no object associated with it
1460  // If this is the case, we associate the object here.
1461  std::map<std::string, const SBase*>::const_iterator pos = this->mIdMap.find(sbmlId);
1462  assert(pos != this->mIdMap.end());
1463 
1464  if (pos->second == NULL)
1465  {
1466  this->mIdMap[sbmlId] = pSBMLReaction;
1467  }
1468  }
1469  else
1470  {
1471  pSBMLReaction = this->mpSBMLDocument->getModel()->createReaction();
1472  this->mCOPASI2SBMLMap[&reaction] = pSBMLReaction;
1473  sbmlId = CSBMLExporter::createUniqueId(this->mIdMap, reaction.getObjectName(), false);
1474  reaction.setSBMLId(sbmlId);
1475  pSBMLReaction->setId(sbmlId);
1476  }
1477 
1478  INIT_DEFAULTS((*pSBMLReaction));
1479 
1480  this->mIdMap.insert(std::pair<const std::string, const SBase*>(sbmlId, pSBMLReaction));
1481  this->mHandledSBMLObjects.insert(pSBMLReaction);
1482 
1483  // don't call setName on level 1 objects because this will also
1484  // change the id
1485  if (this->mpSBMLDocument->getLevel() > 1)
1486  {
1487  pSBMLReaction->setName(reaction.getObjectName().c_str());
1488  }
1489 
1490  pSBMLReaction->setReversible(reaction.isReversible());
1491  const CChemEq& chemicalEquation = reaction.getChemEq();
1492  /* Add all substrates */
1493  unsigned int counter;
1494  std::set<std::string> usedReferences;
1495 
1496  for (counter = 0; counter < chemicalEquation.getSubstrates().size(); counter++)
1497  {
1498  const CChemEqElement* element = chemicalEquation.getSubstrates()[counter];
1499  const CMetab* pMetabolite = element->getMetabolite();
1500  assert(pMetabolite);
1501  SpeciesReference* sRef = NULL;
1502 
1503  if (!(sRef = pSBMLReaction->getReactant(pMetabolite->getSBMLId())))
1504  {
1505  sRef = pSBMLReaction->createReactant();
1506  sRef->setSpecies(pMetabolite->getSBMLId().c_str());
1507  }
1508 
1509  INIT_DEFAULTS((*sRef));
1510 #if LIBSBML_VERSION > 40100
1511 
1512  if (this->mSBMLLevel > 2)
1513  sRef->setConstant(true);
1514 
1515 #endif
1516  sRef->setStoichiometry(element->getMultiplicity());
1517  sRef->setDenominator(1);
1518  usedReferences.insert(sRef->getSpecies());
1519  }
1520 
1521  ListOf* l = pSBMLReaction->getListOfReactants();
1522 
1523  for (counter = l->size(); counter > 0; --counter)
1524  {
1525  if (usedReferences.find(static_cast<SimpleSpeciesReference*>(l->get(counter - 1))->getSpecies()) == usedReferences.end())
1526  {
1527  l->remove(counter - 1);
1528  }
1529  }
1530 
1531  /* Add all products */
1532  usedReferences.clear();
1533 
1534  for (counter = 0; counter < chemicalEquation.getProducts().size(); counter++)
1535  {
1536  const CChemEqElement* element = chemicalEquation.getProducts()[counter];
1537  const CMetab* pMetabolite = element->getMetabolite();
1538  assert(pMetabolite);
1539  SpeciesReference* sRef = NULL;
1540 
1541  if (!(sRef = pSBMLReaction->getProduct(pMetabolite->getSBMLId())))
1542  {
1543  sRef = pSBMLReaction->createProduct();
1544  sRef->setSpecies(pMetabolite->getSBMLId().c_str());
1545  }
1546 
1547  INIT_DEFAULTS((*sRef));
1548 #if LIBSBML_VERSION > 40100
1549 
1550  if (this->mSBMLLevel > 2)
1551  sRef->setConstant(true);
1552 
1553 #endif
1554 
1555  sRef->setStoichiometry(element->getMultiplicity());
1556  sRef->setDenominator(1);
1557  usedReferences.insert(sRef->getSpecies());
1558  }
1559 
1560  l = pSBMLReaction->getListOfProducts();
1561 
1562  for (counter = l->size(); counter > 0; --counter)
1563  {
1564  if (usedReferences.find(static_cast<SimpleSpeciesReference*>(l->get(counter - 1))->getSpecies()) == usedReferences.end())
1565  {
1566  l->remove(counter - 1);
1567  }
1568  }
1569 
1570  /* Add all modifiers */
1571  usedReferences.clear();
1572 
1573  for (counter = 0; counter < chemicalEquation.getModifiers().size(); counter++)
1574  {
1575  const CChemEqElement* element = chemicalEquation.getModifiers()[counter];
1576  const CMetab* pMetabolite = element->getMetabolite(); assert(pMetabolite);
1577  ModifierSpeciesReference* sRef = NULL;
1578 
1579  if (!(sRef = pSBMLReaction->getModifier(pMetabolite->getSBMLId())))
1580  {
1581  if (pSBMLReaction->getLevel() > 1)
1582  {
1583  sRef = pSBMLReaction->createModifier();
1584  assert(sRef != NULL);
1585  sRef->setSpecies(pMetabolite->getSBMLId().c_str());
1586  }
1587  }
1588 
1589  if (pSBMLReaction->getLevel() > 1)
1590  {
1591  usedReferences.insert(sRef->getSpecies());
1592  }
1593  }
1594 
1595  l = pSBMLReaction->getListOfModifiers();
1596 
1597  for (counter = l->size(); counter > 0; --counter)
1598  {
1599  if (usedReferences.find(static_cast<SimpleSpeciesReference*>(l->get(counter - 1))->getSpecies()) == usedReferences.end())
1600  {
1601  l->remove(counter - 1);
1602  }
1603  }
1604 
1605  /* create the kinetic law */
1606 
1607  /* if there is one on COPASI */
1609  {
1610  // make sure the creaated kinetic law has the same level and version as the reaction
1611  // we intend to add it to, otherwise the setKineticLaw function of libsbml 4 will fail
1612  // to set the kinetic law
1613  KineticLaw* pKineticLaw = this->createKineticLaw(reaction, dataModel, pSBMLReaction->getLevel(), pSBMLReaction->getVersion());
1614 
1615  if (pKineticLaw != NULL)
1616  {
1617  pSBMLReaction->setKineticLaw(pKineticLaw);
1618  delete pKineticLaw;
1619  }
1620  else
1621  {
1622  // create an error message and abort
1623  // maybe only abort if incomplete export is not wanted
1624  if (this->mIncompleteExport != true)
1625  {
1627  }
1628  else
1629  {
1630  pSBMLReaction->unsetKineticLaw();
1631  }
1632  }
1633  }
1634  else
1635  {
1636  pSBMLReaction->unsetKineticLaw();
1637  }
1638 
1639  if (pSBMLReaction != NULL)
1640  {
1641  CSBMLExporter::setSBMLNotes(pSBMLReaction, &reaction);
1642  }
1643 
1644  CSBMLExporter::updateMIRIAMAnnotation(&reaction, pSBMLReaction, this->mMetaIdMap);
1645 }
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
static CFunction * getUndefinedFunction()
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
const std::string & getObjectName() const
virtual size_t size() const
const CMetab * getMetabolite() const
bool mIncompleteExport
Definition: CSBMLExporter.h:66
Definition: CMetab.h:178
std::map< std::string, const SBase * > mIdMap
Definition: CSBMLExporter.h:64
static bool setSBMLNotes(SBase *pSBase, const CAnnotation *pAnno)
static const std::string createUniqueId(const std::map< std::string, const SBase * > &idMap, const std::string &prefix, bool addIndexForFirst, const std::string &separator="_")
const std::string & getSBMLId() const
Definition: CReaction.cpp:1654
const CCopasiVector< CChemEqElement > & getProducts() const
Definition: CChemEq.cpp:63
const CFunction * getFunction() const
Definition: CReaction.cpp:252
#define MCSBML
void setSBMLId(const std::string &id)
Definition: CReaction.cpp:1649
const C_FLOAT64 & getMultiplicity() const
const CCopasiVector< CChemEqElement > & getSubstrates() const
Definition: CChemEq.cpp:60
bool isReversible() const
Definition: CReaction.cpp:229
std::map< std::string, const SBase * > mMetaIdMap
Definition: CSBMLExporter.h:70
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
const CCopasiVector< CChemEqElement > & getModifiers() const
Definition: CChemEq.cpp:66
KineticLaw * createKineticLaw(CReaction &reaction, CCopasiDataModel &dataModel, unsigned int level, unsigned int version)
bool updateMIRIAMAnnotation(const CCopasiObject *pCOPASIObject, SBase *pSBMLObject, std::map< std::string, const SBase * > &metaIds)
#define INIT_DEFAULTS(element)
std::set< SBase * > mHandledSBMLObjects
Definition: CSBMLExporter.h:62
const CChemEq & getChemEq() const
Definition: CReaction.cpp:223
void CSBMLExporter::createReactions ( CCopasiDataModel dataModel)
protected

Creates the reactions for the model.

Definition at line 1417 of file CSBMLExporter.cpp.

References CCopasiVector< T >::begin(), createReaction(), CCopasiVector< T >::end(), CCopasiDataModel::getModel(), CModel::getReactions(), and mpSBMLDocument.

Referenced by createSBMLDocument().

1418 {
1419  // make sure the SBML Document already exists and that it has a Model set
1420  if (dataModel.getModel() == NULL || this->mpSBMLDocument == NULL || this->mpSBMLDocument->getModel() == NULL) return;
1421 
1422  CCopasiVectorNS<CReaction>::const_iterator it = dataModel.getModel()->getReactions().begin(), endit = dataModel.getModel()->getReactions().end();
1423 
1424  while (it != endit)
1425  {
1426  createReaction(**it, dataModel);
1427  ++it;
1428  }
1429 }
void createReaction(CReaction &reaction, CCopasiDataModel &dataModel)
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
iterator begin()
iterator end()
CCopasiVectorNS< CReaction > & getReactions()
Definition: CModel.cpp:1039
void CSBMLExporter::createRule ( const CModelEntity modelEntity,
CCopasiDataModel dataModel,
Rule *  pOldRule 
)
protected

Creates the rule for the given COPASI model entity.

Definition at line 1937 of file CSBMLExporter.cpp.

References CModelEntity::ASSIGNMENT, convertExpression(), convertToASTNode(), createFunctionSetFromFunctionNames(), CCopasiMessage::ERROR, CCopasiMessage::EXCEPTION, findDirectlyUsedFunctions(), CModelEntity::FIXED, CMetab::getCompartment(), CCompartment::getDimensionality(), CModelEntity::getExpression(), CModelEntity::getExpressionPtr(), CCopasiRootContainer::getFunctionList(), CCopasiObject::getObjectName(), CCopasiObject::getObjectType(), CEvaluationTree::getRoot(), CModelEntity::getSBMLId(), CModelEntity::getStatus(), CEvaluationNode::getType(), CModelEntity::getValueReference(), CEvaluationNode::INVALID, isExpressionSBMLCompatible(), mCOPASI2SBMLMap, MCSBML, mIncompatibilities, mIncompleteExport, mInitialValueMap, mpSBMLDocument, mSBMLLevel, mSBMLVersion, multiplyByObject(), mUsedFunctions, outputIncompatibilities(), replace_local_parameters(), replaceSpeciesReferences(), CEvaluationTree::setInfix(), and CEvaluationNode::type().

Referenced by createRules().

1938 {
1939  // check the expression
1940  std::vector<SBMLIncompatibility> result;
1942  , dataModel
1943  , this->mSBMLLevel
1944  , this->mSBMLVersion
1945  , result
1946  , std::string("rule for object named \"" + modelEntity.getObjectName() + "\"").c_str()
1947  , false
1948  , &mInitialValueMap);
1949 
1950  // collect directly used functions
1951  if (result.empty())
1952  {
1953  std::set<std::string> directlyUsedFunctionNames;
1954  CSBMLExporter::findDirectlyUsedFunctions(modelEntity.getExpressionPtr()->getRoot(), directlyUsedFunctionNames);
1955  std::set<CFunction*> usedFunctions = CSBMLExporter::createFunctionSetFromFunctionNames(directlyUsedFunctionNames, CCopasiRootContainer::getFunctionList());
1956 
1957 # if defined _MSC_VER && _MSC_VER < 1201 // 1200 Identifies Visual C++ 6.0
1958  {
1959  std::set<CFunction*>::const_iterator it = usedFunctions.begin();
1960  std::set<CFunction*>::const_iterator end = usedFunctions.end();
1961 
1962  for (; it != end; ++it)
1963  this->mUsedFunctions.insert(*it);
1964  }
1965 #else
1966  this->mUsedFunctions.insert(usedFunctions.begin(), usedFunctions.end());
1967 #endif
1968 
1969  // create the actual rule
1970  //Rule* pRule = this->mpSBMLDocument->getModel()->getRule(modelEntity.getSBMLId());
1971  const CMetab* pMetab = dynamic_cast<const CMetab*>(&modelEntity);
1972 
1973  if (pOldRule == NULL)
1974  {
1975  if (modelEntity.getStatus() == CModelEntity::ASSIGNMENT)
1976  {
1977  pOldRule = this->mpSBMLDocument->getModel()->createAssignmentRule();
1978  }
1979  else
1980  {
1981  if (pMetab != NULL)
1982  {
1983  // check if the compartment is fixed
1984  if (pMetab->getCompartment()->getStatus() != CModelEntity::FIXED)
1985  {
1986  CCopasiMessage(CCopasiMessage::ERROR, MCSBML + 52, pMetab->getObjectName().c_str());
1987  }
1988  }
1989 
1990  pOldRule = this->mpSBMLDocument->getModel()->createRateRule();
1991  }
1992 
1993  pOldRule->setVariable(modelEntity.getSBMLId());
1994  }
1995  else
1996  {
1997  // Read the rule to the model
1998  this->mpSBMLDocument->getModel()->getListOfRules()->appendAndOwn(pOldRule);
1999  }
2000 
2001  // set the math
2002 
2003  const std::string& changedExpression = convertExpression(modelEntity.getExpression(), mInitialValueMap);
2004  CEvaluationTree tree;
2005  tree.setInfix(changedExpression);
2006  const CEvaluationNode* pOrigNode = tree.getRoot();
2007 
2009  {
2010  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 70, "assignment", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
2011  }
2012 
2013  // the next few lines replace references to species depending on whether
2014  // it is a reference to an amount or a reference to a concentration.
2015  // Other factors that influence this replacement are if the model
2016  // contains variable volumes or if the quantity units are set to CModel::number
2017  pOrigNode = this->replaceSpeciesReferences(pOrigNode, dataModel);
2018  assert(pOrigNode != NULL);
2019 
2020  // check if the rule is for an amount species
2021  // if this is the case, we have to multiply the expression by the volume
2022  // of the compartment the species is in
2023  if (pMetab != NULL)
2024  {
2025  std::map<const CCopasiObject*, SBase*>::const_iterator pos = this->mCOPASI2SBMLMap.find(&modelEntity);
2026  assert(pos != this->mCOPASI2SBMLMap.end());
2027 
2028  if (dynamic_cast<const Species*>(pos->second)->getHasOnlySubstanceUnits() == true)
2029  {
2030  const CCompartment* pCompartment = pMetab->getCompartment();
2031 
2032  if (pCompartment->getDimensionality() != 0)
2033  {
2034  CEvaluationNode* pNode = CSBMLExporter::multiplyByObject(pOrigNode, pCompartment->getValueReference());
2035  assert(pNode != NULL);
2036 
2037  if (pNode != NULL)
2038  {
2039  delete pOrigNode;
2040  pOrigNode = pNode;
2041  }
2042  }
2043  }
2044  }
2045 
2046  ASTNode* pNode = this->convertToASTNode(pOrigNode, dataModel);
2047  this->replace_local_parameters(pNode, dataModel);
2048  delete pOrigNode;
2049 
2050  if (pNode != NULL)
2051  {
2052  pOldRule->setMath(pNode);
2053  delete pNode;
2054  }
2055  else
2056  {
2057  if (this->mIncompleteExport != true)
2058  {
2059  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "rule", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
2060  }
2061  }
2062  }
2063  else
2064  {
2065  this->mIncompatibilities.insert(this->mIncompatibilities.end(), result.begin(), result.end());
2066 
2067  if (!this->mIncompleteExport)
2068  {
2069  this->outputIncompatibilities();
2070  CCopasiMessage(CCopasiMessage::EXCEPTION, MCSBML + 60, "rule", modelEntity.getObjectType().c_str(), modelEntity.getObjectName().c_str());
2071  }
2072  }
2073 }
const CExpression * getExpressionPtr() const
static void findDirectlyUsedFunctions(const CEvaluationNode *pRootNode, std::set< std::string > &result)
unsigned int mSBMLLevel
Definition: CSBMLExporter.h:56
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
void replace_local_parameters(ASTNode *pOrigNode, const CCopasiDataModel &dataModel)
std::string convertExpression(const std::string &expression, const std::map< const std::string, Parameter * > &initialValueMap)
const std::string & getSBMLId() const
static CEvaluationNode * multiplyByObject(const CEvaluationNode *pOrigNode, const CCopasiObject *pObject)
const std::string & getObjectName() const
unsigned C_INT32 getDimensionality() const
const Type & getType() const
const std::string & getObjectType() const
std::string getExpression() const
bool mIncompleteExport
Definition: CSBMLExporter.h:66
Definition: CMetab.h:178
std::map< const std::string, Parameter * > mInitialValueMap
Definition: CSBMLExporter.h:79
static Type type(const Type &type)
#define MCSBML
unsigned int mSBMLVersion
Definition: CSBMLExporter.h:57
static CFunctionDB * getFunctionList()
std::vector< SBMLIncompatibility > mIncompatibilities
Definition: CSBMLExporter.h:65
std::map< const CCopasiObject *, SBase * > mCOPASI2SBMLMap
Definition: CSBMLExporter.h:61
ASTNode * convertToASTNode(const CEvaluationNode *pOrig, CCopasiDataModel &dataModel)
static void isExpressionSBMLCompatible(const CEvaluationTree &expr, const CCopasiDataModel &dataModel, int sbmlLevel, int sbmlVersion, std::vector< SBMLIncompatibility > &result, const std::string &objectDescription, bool initialExression=false, std::map< const std::string, Parameter * > *initialMap=NULL)
CEvaluationNode * replaceSpeciesReferences(const CEvaluationNode *pOrigNode, const CCopasiDataModel &dataModel)
void outputIncompatibilities() const
static const std::set< CFunction * > createFunctionSetFromFunctionNames(const std::set< std::string > &names, CFunctionDB *pFunDB)
const CModelEntity::Status & getStatus() const
std::set< CFunction * > mUsedFunctions
Definition: CSBMLExporter.h:63
const CCompartment * getCompartment() const
Definition: CMetab.cpp:222
CEvaluationNode * getRoot()
virtual bool setInfix(const std::string &infix)
CCopasiObject * getValueReference() const
void CSBMLExporter::createRules ( CCopasiDataModel dataModel)
protected

Creates the rules for the model.

Definition at line 1835 of file CSBMLExporter.cpp.

References createRule(), CModelEntity::getSBMLId(), mODEVector, mpSBMLDocument, and orderRules().

Referenced by createSBMLDocument().

1836 {
1837  // make sure the mAssignmentVector has been filled already
1838  // make sure the mODEVector has been filled already
1839  // order the rules for Level 1 export
1840  // rules in Level 2 are not ordered.
1841  //if (this->mSBMLLevel == 1 || (this->mSBMLLevel == 2 && this->mSBMLVersion == 1))
1842  // {
1843  std::vector<CModelEntity*> orderedAssignmentRules = orderRules(dataModel);
1844  //}
1845  //
1846  // remove all rules from the SBML model
1847  // and put them in a map
1848  std::map<std::string, Rule*> ruleMap;
1849  Model* pSBMLModel = this->mpSBMLDocument->getModel();
1850  assert(pSBMLModel != NULL);
1851 
1852  while (pSBMLModel->getNumRules() != 0)
1853  {
1854  Rule* pRule = pSBMLModel->getRule(0);
1855  assert(pRule != NULL);
1856 
1857  // ignore algebraic rules
1858  if (pRule->getTypeCode() == SBML_ASSIGNMENT_RULE)
1859  {
1860  AssignmentRule* pARule = dynamic_cast<AssignmentRule*>(pRule);
1861  assert(pARule != NULL);
1862  ruleMap[pARule->getVariable()] = pARule;
1863  }
1864  else if (pRule->getTypeCode() == SBML_RATE_RULE)
1865  {
1866  RateRule* pRRule = dynamic_cast<RateRule*>(pRule);
1867  assert(pRRule != NULL);
1868  ruleMap[pRRule->getVariable()] = pRRule;
1869  }
1870 
1871  pSBMLModel->getListOfRules()->remove(0);
1872  }
1873 
1874  // create the rules
1875  const CModelEntity* pME = NULL;
1876  size_t i, iMax = orderedAssignmentRules.size();
1877 
1878  for (i = 0; i < iMax; ++i)
1879  {
1880  pME = orderedAssignmentRules[i];
1881  assert(pME != NULL);
1882 
1883  if (pME != NULL)
1884  {
1885  std::map<std::string, Rule*>::const_iterator pos = ruleMap.find(pME->getSBMLId());
1886  Rule* pOldRule = NULL;
1887 
1888  if (pos != ruleMap.end())
1889  {
1890  pOldRule = pos->second;
1891  assert(pOldRule != NULL);
1892  ruleMap.erase(pos->first);
1893  }
1894 
1895  createRule(*pME, dataModel, pOldRule);
1896  }
1897  }
1898 
1899  iMax = mODEVector.size();
1900 
1901  for (i = 0; i < iMax; ++i)
1902  {
1903  pME = mODEVector[i];
1904  assert(pME != NULL);
1905 
1906  if (pME != NULL)
1907  {
1908  std::map<std::string, Rule*>::const_iterator pos = ruleMap.find(pME->getSBMLId());
1909  Rule* pOldRule = NULL;
1910 
1911  if (pos != ruleMap.end())
1912  {
1913  pOldRule = pos->second;
1914  assert(pOldRule != NULL);
1915  ruleMap.erase(pos->first);
1916  }
1917 
1918  createRule(*pME, dataModel, pOldRule);
1919  }
1920  }
1921 
1922  // delete the remaining rules
1923  std::map<std::string, Rule*>::iterator mapIt = ruleMap.begin(), mapEndit = ruleMap.end();
1924 
1925  while (mapIt != mapEndit)
1926  {
1927  delete mapIt->second;
1928  ++mapIt;
1929  }
1930 
1931  ruleMap.clear();
1932 }
std::vector< CModelEntity * > orderRules(const CCopasiDataModel &dataModel)
SBMLDocument * mpSBMLDocument
Definition: CSBMLExporter.h:55
const std::string & getSBMLId() const
std::vector< CModelEntity * > mODEVector
Definition: CSBMLExporter.h:59
void createRule(const CModelEntity &modelEntity, CCopasiDataModel &dataModel, Rule *pOldRule)
void CSBMLExporter::createSBMLDocument ( CCopasiDataModel dataModel)
protected

Creates an SBMLDocument from the given CCopasiDataModelObject. It checks if an SBMLDocument already exists from an import and if this is the case, the old document is copied. If none exists a new one is created. Copying the old one makes sure that if something goes wrong during export, the original model is still consistent.

Definition at line 3399 of file CSBMLExporter.cpp.

References addInitialAssignmentsToModel(), assignSBMLIdsToReactions(), checkForInitialAssignments(), SBMLUtils::collectIds(), collectIds(), convertToLevel1(), createCompartments(), createEvents(), createFunctionDefinitions(), createInitialAssignments(), createMetabolites(), createParameters(), createReactions(), createRules(), createUniqueId(), createUnits(), CCopasiMessage::EXCEPTION, fatalError, findAvogadro(), CCopasiDataModel::getCurrentSBMLDocument(), CModelEntity::getKey(), CCopasiDataModel::getModel(), CCopasiObject::getObjectName(), CModelEntity::getSBMLId(), hasVolumeAssignment(), mAvogadroCreated, mCOPASI2SBMLMap, mExportedFunctions, mFunctionIdMap, mFunctionMap, mHaveModelHistoryAuthorWarning, mHaveModelHistoryCreationDateWarning, mHaveModelHistoryModificationDateWarning, mIdMap, mIncompatibilities, mIncompleteExport, mInitialValueMap, mMetaIdMap, mpAvogadro, mpSBMLDocument, mSBMLLevel, mSBMLVersion, mVariableVolumes, outputIncompatibilities(), CModel::removeModelValue(), setSBMLNotes(), updateCOPASI2SBMLMap(), and updateMIRIAMAnnotation().

Referenced by exportModelToString().

3400 {
3401  // reset warnings for missing entries in modelhistory
3405 
3406  const SBMLDocument* pOldSBMLDocument = dataModel.getCurrentSBMLDocument();
3407  const CModel* pModel = dataModel.getModel();
3408  assert(pModel != NULL);
3409 
3410  if (pOldSBMLDocument == NULL)
3411  {
3412  this->mpSBMLDocument = new SBMLDocument(this->mSBMLLevel, this->mSBMLVersion);
3413  }
3414  else
3415  {
3416  this->mpSBMLDocument = dynamic_cast<SBMLDocument*>(pOldSBMLDocument->clone());
3417  }
3418 
3419  if (this->mpSBMLDocument == NULL) fatalError();
3420 
3421 #if LIBSBML_VERSION >= 50000
3422  const std::string uri = (this->mSBMLLevel < 3 ? LayoutExtension::getXmlnsL2() : LayoutExtension::getXmlnsL3V1V1());
3423  this->mpSBMLDocument->enablePackage(uri, "layout", true);
3424 
3425  if (this->mSBMLLevel > 2)
3426  this->mpSBMLDocument->setPackageRequired("layout", false);
3427 
3428  const std::string renderuri = (this->mSBMLLevel < 3 ? RenderExtension::getXmlnsL2() : RenderExtension::getXmlnsL3V1V1());
3429  this->mpSBMLDocument->enablePackage(renderuri, "render", true);
3430 
3431  if (this->mSBMLLevel > 2)
3432  this->mpSBMLDocument->setPackageRequired("render", false);
3433 
3434 #endif
3435 
3436  if (this->mpSBMLDocument->getModel() == NULL)
3437  {
3438  // there might still be COPASI object that have an SBML id, we have to
3439  // collect those as well
3440  CSBMLExporter::collectIds(dataModel, this->mIdMap);
3441  std::string id = pModel->getSBMLId();
3442 
3443  if (id.empty())
3444  {
3445  id = CSBMLExporter::createUniqueId(this->mIdMap, pModel->getObjectName(), false);
3446  this->mIdMap.insert(std::pair<const std::string, const SBase*>(id, this->mpSBMLDocument->getModel()));
3447  }
3448 
3449  this->mpSBMLDocument->createModel(id);
3450  }
3451  else
3452  {
3453  SBMLUtils::collectIds(this->mpSBMLDocument->getModel(), this->mIdMap, this->mMetaIdMap);
3454  }
3455 
3456  this->mFunctionIdMap.clear();
3457  // update the copasi2sbmlmap
3458  updateCOPASI2SBMLMap(dataModel);
3459  // update the comments on the model
3460  this->mpSBMLDocument->getModel()->setName(pModel->getObjectName());
3461 
3462  if (pModel != NULL && this->mpSBMLDocument->getModel() != NULL)
3463  {
3464  CSBMLExporter::setSBMLNotes(this->mpSBMLDocument->getModel(), pModel);
3465  }
3466 
3467  // update the MIRIAM annotation on the model
3468  CSBMLExporter::updateMIRIAMAnnotation(pModel, this->mpSBMLDocument->getModel(), this->mMetaIdMap);
3469 #if LIBSBML_VERSION >= 40100
3470 
3471  if (this->mSBMLLevel > 2)
3472  {
3473  // we have to remove the conversionFactor because on import we multiplied the stoichiometries
3474  // with this factor
3475  this->mpSBMLDocument->getModel()->unsetConversionFactor();
3476  }
3477 
3478 #endif // LIBSBML_VERSION
3479 
3480  // create units, compartments, species, parameters, reactions, initial
3481  // assignment, assignments, (event) and function definitions
3482  createUnits(dataModel);
3483  // try to find a parameter that represents Avogadros number
3484  findAvogadro(dataModel);
3485 
3486  // check if there is an assignment to a volume
3487  // in that case we has to export all species with the
3488  // hasOnlySubstanceUnits flag set to true
3489  this->mVariableVolumes = this->hasVolumeAssignment(dataModel);
3490 
3491  createCompartments(dataModel);
3492  createMetabolites(dataModel);
3493  createParameters(dataModel);
3494 
3495  // TODO here we should check the expressions but the function definitions
3496  // TODO have not been created yet, so we can't
3497  // TODO Maybe we don't have to do all checks here.
3498  // TODO it would probably be enough to check if the expressions are valid and
3499  // TODO to check the function calls later on when the functions are created.
3500 
3501  // only export initial assignments for Level 2 Version 2 and above
3502  if (this->mSBMLLevel != 1 && !(this->mSBMLLevel == 2 && this->mSBMLVersion == 1))
3503  {
3504  createInitialAssignments(dataModel);
3505  }
3506  else
3507  {
3509  }
3510 
3511  // since the flux of a reaction can be referenced in an assignment,
3512  // we have to make sure that asll reactions do have SBML Ids prior to creating the rules
3513  // and events
3514  assignSBMLIdsToReactions(dataModel.getModel());
3515 
3516  createRules(dataModel);
3517  createEvents(dataModel);
3518 
3519  // we have to export the reactions after all other entities that have
3520  // expressions since an expression could contain a local parameter
3521  // If it did, it would have to be converted to a global parameter and that
3522  // has to be taken into consideration when creating the reactions
3523  createReactions(dataModel);
3524  // find all used functions
3525  createFunctionDefinitions(dataModel);
3526 
3527  if (this->mSBMLLevel == 1)
3528  {
3529  // do SBML Level1 Voodoo
3530  // e.g. replace some of the unsupported nodes with workarounds
3531  convertToLevel1();
3532  // delete all function definitions since L1 does not have functions
3533  Model* pSBMLModel = this->mpSBMLDocument->getModel();
3534  assert(pSBMLModel != NULL);
3535  int i = pSBMLModel->getListOfFunctionDefinitions()->size();
3536 
3537  while (i > 0)
3538  {
3539  --i;
3540  // fix for bug 1086
3541  // remove the object from the COPASI2SBML Map
3542  std::map<const CCopasiObject*, SBase*>::iterator it = this->mCOPASI2SBMLMap.begin(), endit = this->mCOPASI2SBMLMap.end();
3543 
3544  while (it != endit)
3545  {
3546  if (it->second == pSBMLModel->getFunctionDefinition(i))
3547  {
3548  this->mCOPASI2SBMLMap.erase(it);
3549  break;
3550  }
3551 
3552  ++it;
3553  }
3554 
3555  delete pSBMLModel->getListOfFunctionDefinitions()->remove(i);
3556  }
3557  }
3558  else
3559  {
3560  // add all function definitions to the model
3561  Model* pSBMLModel = this->mpSBMLDocument->getModel();
3562  assert(pSBMLModel != NULL);
3563 
3564  if (pSBMLModel != NULL)
3565  {
3566  unsigned int i = 0, iMax = this->mExportedFunctions.size();
3567 #if LIBSBML_VERSION >= 40100
3568  int result;
3569 #endif // LIBSBML_VERSION >= 40100
3570  FunctionDefinition* pFunDef = NULL;
3571  std::map<const FunctionDefinition*, const CCopasiObject*>::const_iterator funPos;
3572 
3573  while (i < iMax)
3574  {
3575  pFunDef = this->mExportedFunctions.get(i);
3576  assert(pFunDef != NULL);
3577  // match the namespaces to those of the model
3578  pFunDef->setSBMLNamespaces(pSBMLModel->getSBMLNamespaces());
3579 // add methods only return a value starting with libsbml 4
3580 #if LIBSBML_VERSION >= 40100
3581  result = pSBMLModel->addFunctionDefinition(pFunDef);
3582  assert(result == LIBSBML_OPERATION_SUCCESS);
3583 #else
3584  pSBMLModel->addFunctionDefinition(pFunDef);
3585  assert(pSBMLModel->getFunctionDefinition(pFunDef->getId()) != NULL);
3586 #endif // LIBSBML_VERSION >= 40100
3587  // now we need to add the newly created FunctionDefinition to the copasi2sbml map
3588  funPos = this->mFunctionMap.find(pFunDef);
3589  assert(funPos != this->mFunctionMap.end());
3590  pFunDef = pSBMLModel->getFunctionDefinition(pFunDef->getId());
3591  assert(pFunDef != NULL);
3592  this->mCOPASI2SBMLMap[funPos->second] = pFunDef;
3593  ++i;
3594  }
3595 
3596  //the assert below no longer holds, as we export uniform / normal as functiondefinitions
3597  //assert(pSBMLModel->getNumFunctionDefinitions() == this->mExportedFunctions.size());
3598  }
3599  }
3600 
3601  // In case the document is just a clone of an old model, we have to set the level and version
3602  if (this->mpSBMLDocument->getLevel() != this->mSBMLLevel || this->mpSBMLDocument->getVersion() != this->mSBMLVersion)
3603  {
3604 #if LIBSBML_VERSION >= 50400
3605 
3606  SBMLNamespaces targetNs(mSBMLLevel, mSBMLVersion); // use reference, as the ns gets cloned
3607 
3608  if (mSBMLLevel == 1 && mSBMLVersion == 1)
3609  {
3610  // l1v1 export tailor made to suit GEPASI, with pow -> ^ notation and
3611  // inlining of compartment sizes in kinetics.
3612 
3613  ConversionProperties prop(&targetNs);
3614  prop.addOption("convertToL1V1", true,
3615  "convert the document to SBML Level 1 Version 1");
3616  prop.addOption("changePow", true,
3617  "change pow expressions to the (^) hat notation");
3618  prop.addOption("inlineCompartmentSizes", true,
3619  "if true, occurrances of compartment ids in expressions will be replaced with their initial size");
3620 
3621  mpSBMLDocument->convert(prop);
3622  }
3623  else
3624  {
3625 
3626  ConversionProperties prop(&targetNs);
3627  prop.addOption("strict", false);
3628  prop.addOption("setLevelAndVersion", true);
3629  prop.addOption("ignorePackages", true);
3630 
3631  mpSBMLDocument->convert(prop);
3632  }
3633 
3634 #else
3635  this->mpSBMLDocument->setLevelAndVersion(this->mSBMLLevel, this->mSBMLVersion);
3636 #endif
3637  }
3638 
3639  if (this->mpSBMLDocument->getLevel() != this->mSBMLLevel || this->mpSBMLDocument->getVersion() != this->mSBMLVersion)
3640  {
3641  unsigned int i, iMax = this->mpSBMLDocument->getNumErrors();
3642  std::string message("libSBML could not convert the model to the requested level and/or version. The reason(s) given were:");
3643 
3644  for (i = 0; i < iMax ; ++i)
3645  {
3646  const XMLError* pSBMLError = this->mpSBMLDocument->getError(i);
3647  message += "\n";
3648  message += pSBMLError->getMessage();
3649  }
3650 
3651  CCopasiMessage(CCopasiMessage::EXCEPTION, message.c_str());
3652  }
3653 
3654  // remove mpAvogadro from the model again
3655  if (this->mAvogadroCreated == true)
3656  {
3657  std::map<const CCopasiObject*, SBase*>::iterator pos = this->mCOPASI2SBMLMap.find(this->mpAvogadro);
3658  this->mCOPASI2SBMLMap.erase(pos);
3659  dataModel.getModel()->removeModelValue(this->mpAvogadro->getKey(), true);
3660  }
3661 
3662  this->outputIncompatibilities();
3663 
3664  // if the model is incompatible with SBML export, throw an exception
3665  if (!this->mIncompatibilities.empty() && !this->mIncompleteExport)
3666  {
3667  CCopasiMessage(CCopasiMessage::EXCEPTION, "Model incompatible with chosen version and/or level of SBML.");
3668  }
3669 
3670  // if initial assignments were used we will have to add them to the document
3672  mInitialValueMap.clear();