END_TEST START_TEST ( test_KineticLaw_parent_NULL ) { Reaction * r = new Reaction(2, 4); KineticLaw *kl = r->createKineticLaw(); Parameter *p = kl->createParameter(); fail_unless(r == kl->getParentSBMLObject()); fail_unless(r == p->getAncestorOfType(SBML_REACTION)); fail_unless(kl == p->getAncestorOfType(SBML_KINETIC_LAW)); KineticLaw *kl1 = kl->clone(); fail_unless(kl1->getParentSBMLObject() == NULL); fail_unless(kl1->getParameter(0)->getAncestorOfType(SBML_REACTION) == NULL); fail_unless(kl1 == kl1->getParameter(0)->getAncestorOfType(SBML_KINETIC_LAW)); delete r; }
/** * * Creates an SBML model represented in "7.1 A Simple example application of SBML" * in the SBML Level 2 Version 4 Specification. * */ SBMLDocument* createExampleEnzymaticReaction() { const unsigned int level = Level; const unsigned int version = Version; //--------------------------------------------------------------------------- // // Creates an SBMLDocument object // //--------------------------------------------------------------------------- SBMLDocument* sbmlDoc = new SBMLDocument(level,version); //--------------------------------------------------------------------------- // // Creates a Model object inside the SBMLDocument object. // //--------------------------------------------------------------------------- Model* model = sbmlDoc->createModel(); model->setId("EnzymaticReaction"); //--------------------------------------------------------------------------- // // Creates UnitDefinition objects inside the Model object. // //--------------------------------------------------------------------------- // Temporary pointers (reused more than once below). UnitDefinition* unitdef; Unit* unit; //--------------------------------------------------------------------------- // (UnitDefinition1) Creates an UnitDefinition object ("per_second") //--------------------------------------------------------------------------- unitdef = model->createUnitDefinition(); unitdef->setId("per_second"); // Creates an Unit inside the UnitDefinition object unit = unitdef->createUnit(); unit->setKind(UNIT_KIND_SECOND); unit->setExponent(-1); //-------------------------------------------------------------------------------- // (UnitDefinition2) Creates an UnitDefinition object ("litre_per_mole_per_second") //-------------------------------------------------------------------------------- // Note that we can reuse the pointers 'unitdef' and 'unit' because the // actual UnitDefinition object (along with the Unit objects within it) // is already attached to the Model object. unitdef = model->createUnitDefinition(); unitdef->setId("litre_per_mole_per_second"); // Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second") unit = unitdef->createUnit(); unit->setKind(UNIT_KIND_MOLE); unit->setExponent(-1); // Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second") unit = unitdef->createUnit(); unit->setKind(UNIT_KIND_LITRE); unit->setExponent(1); // Creates an Unit inside the UnitDefinition object ("litre_per_mole_per_second") unit = unitdef->createUnit(); unit->setKind(UNIT_KIND_SECOND); unit->setExponent(-1); //--------------------------------------------------------------------------- // // Creates a Compartment object inside the Model object. // //--------------------------------------------------------------------------- Compartment* comp; const string compName = "cytosol"; // Creates a Compartment object ("cytosol") comp = model->createCompartment(); comp->setId(compName); // Sets the "size" attribute of the Compartment object. // // We are not setting the units on the compartment size explicitly, so // the units of this Compartment object will be the default SBML units of // volume, which are liters. // comp->setSize(1e-14); //--------------------------------------------------------------------------- // // Creates Species objects inside the Model object. // //--------------------------------------------------------------------------- // Temporary pointer (reused more than once below). Species *sp; //--------------------------------------------------------------------------- // (Species1) Creates a Species object ("ES") //--------------------------------------------------------------------------- // Create the Species objects inside the Model object. sp = model->createSpecies(); sp->setId("ES"); sp->setName("ES"); // Sets the "compartment" attribute of the Species object to identify the // compartment in which the Species object is located. sp->setCompartment(compName); // Sets the "initialAmount" attribute of the Species object. // // In SBML, the units of a Species object's initial quantity are // determined by two attributes, "substanceUnits" and // "hasOnlySubstanceUnits", and the "spatialDimensions" attribute // of the Compartment object ("cytosol") in which the species // object is located. Here, we are using the default values for // "substanceUnits" (which is "mole") and "hasOnlySubstanceUnits" // (which is "false"). The compartment in which the species is // located uses volume units of liters, so the units of these // species (when the species appear in numerical formulas in the // model) will be moles/liters. // sp->setInitialAmount(0); //--------------------------------------------------------------------------- // (Species2) Creates a Species object ("P") //--------------------------------------------------------------------------- sp = model->createSpecies(); sp->setCompartment(compName); sp->setId("P"); sp->setName("P"); sp->setInitialAmount(0); //--------------------------------------------------------------------------- // (Species3) Creates a Species object ("S") //--------------------------------------------------------------------------- sp = model->createSpecies(); sp->setCompartment(compName); sp->setId("S"); sp->setName("S"); sp->setInitialAmount(1e-20); //--------------------------------------------------------------------------- // (Species4) Creates a Species object ("E") //--------------------------------------------------------------------------- sp = model->createSpecies(); sp->setCompartment(compName); sp->setId("E"); sp->setName("E"); sp->setInitialAmount(5e-21); //--------------------------------------------------------------------------- // // Creates Reaction objects inside the Model object. // //--------------------------------------------------------------------------- // Temporary pointers. Reaction* reaction; SpeciesReference* spr; KineticLaw* kl; //--------------------------------------------------------------------------- // (Reaction1) Creates a Reaction object ("veq"). //--------------------------------------------------------------------------- reaction = model->createReaction(); reaction->setId("veq"); // (Reactant1) Creates a Reactant object that references Species "E" // in the model. The object will be created within the reaction in the // SBML <listOfReactants>. spr = reaction->createReactant(); spr->setSpecies("E"); // (Reactant2) Creates a Reactant object that references Species "S" // in the model. spr = reaction->createReactant(); spr->setSpecies("S"); //--------------------------------------------------------------------------- // (Product1) Creates a Product object that references Species "ES" in // the model. //--------------------------------------------------------------------------- spr = reaction->createProduct(); spr->setSpecies("ES"); //--------------------------------------------------------------------------- // Creates a KineticLaw object inside the Reaction object ("veq"). //--------------------------------------------------------------------------- kl = reaction->createKineticLaw(); //--------------------------------------------------------------------------- // Creates an ASTNode object which represents the following math of the // KineticLaw. // // <math xmlns="http://www.w3.org/1998/Math/MathML"> // <apply> // <times/> // <ci> cytosol </ci> // <apply> // <minus/> // <apply> // <times/> // <ci> kon </ci> // <ci> E </ci> // <ci> S </ci> // </apply> // <apply> // <times/> // <ci> koff </ci> // <ci> ES </ci> // </apply> // </apply> // </apply> // </math> // //--------------------------------------------------------------------------- //------------------------------------------ // // create nodes representing the variables // //------------------------------------------ ASTNode* astCytosol = new ASTNode(AST_NAME); astCytosol->setName("cytosol"); ASTNode* astKon = new ASTNode(AST_NAME); astKon->setName("kon"); ASTNode* astKoff = new ASTNode(AST_NAME); astKoff->setName("koff"); ASTNode* astE = new ASTNode(AST_NAME); astE->setName("E"); ASTNode* astS = new ASTNode(AST_NAME); astS->setName("S"); ASTNode* astES = new ASTNode(AST_NAME); astES->setName("ES"); //-------------------------------------------- // // create node representing // <apply> // <times/> // <ci> koff </ci> // <ci> ES </ci> // </apply> // //-------------------------------------------- ASTNode *astTimes1 = new ASTNode(AST_TIMES); astTimes1->addChild(astKoff); astTimes1->addChild(astES); //-------------------------------------------- // // create node representing // <apply> // <times/> // <ci> kon </ci> // <ci> E </ci> // <ci> S </ci> // </apply> // // // (NOTES) // // Since there is a restriction with an ASTNode of "<times/>" operation // such that the ASTNode is a binary class and thus only two operands can // be directly added, the following code in this comment block is invalid // because the code directly adds three <ci> ASTNodes to <times/> ASTNode. // // ASTNode *astTimes = new ASTNode(AST_TIMES); // astTimes->addChild(astKon); // astTimes->addChild(astE); // astTimes->addChild(astS); // // The following valid code after this comment block creates the ASTNode // as a binary tree. // // Please see "Converting between ASTs and text strings" described // at http://sbml.org/Software/libSBML/docs/cpp-api/class_a_s_t_node.html // for the detailed information. // //-------------------------------------------- ASTNode *astTimes2 = new ASTNode(AST_TIMES); astTimes2->addChild(astE); astTimes2->addChild(astS); ASTNode *astTimes = new ASTNode(AST_TIMES); astTimes->addChild(astKon); astTimes->addChild(astTimes2); //-------------------------------------------- // // create node representing // <apply> // <minus/> // <apply> // <times/> // <ci> kon </ci> // <ci> E </ci> // <ci> S </ci> // </apply> // <apply> // <times/> // <ci> koff </ci> // <ci> ES </ci> // </apply> // </apply> // //-------------------------------------------- ASTNode *astMinus = new ASTNode(AST_MINUS); astMinus->addChild(astTimes); astMinus->addChild(astTimes1); //-------------------------------------------- // // create node representing // <apply> // <times/> // <ci> cytosol </ci> // <apply> // <minus/> // <apply> // <times/> // <ci> kon </ci> // <ci> E </ci> // <ci> S </ci> // </apply> // <apply> // <times/> // <ci> koff </ci> // <ci> ES </ci> // </apply> // </apply> // </apply> // //-------------------------------------------- ASTNode* astMath = new ASTNode(AST_TIMES); astMath->addChild(astCytosol); astMath->addChild(astMinus); //--------------------------------------------- // // set the Math element // //------------------------------------------------ kl->setMath(astMath); // KineticLaw::setMath(const ASTNode*) sets the math of the KineticLaw object // to a copy of the given ASTNode, and thus basically the caller should delete // the original ASTNode object if the caller has the ownership of the object to // avoid memory leak. delete astMath; //--------------------------------------------------------------------------- // Creates local Parameter objects inside the KineticLaw object. //--------------------------------------------------------------------------- // Creates a Parameter ("kon") Parameter* para = kl->createParameter(); para->setId("kon"); para->setValue(1000000); para->setUnits("litre_per_mole_per_second"); // Creates a Parameter ("koff") para = kl->createParameter(); para->setId("koff"); para->setValue(0.2); para->setUnits("per_second"); //--------------------------------------------------------------------------- // (Reaction2) Creates a Reaction object ("vcat") . //--------------------------------------------------------------------------- reaction = model->createReaction(); reaction->setId("vcat"); reaction->setReversible(false); //--------------------------------------------------------------------------- // Creates Reactant objects inside the Reaction object ("vcat"). //--------------------------------------------------------------------------- // (Reactant1) Creates a Reactant object that references Species "ES" in the // model. spr = reaction->createReactant(); spr->setSpecies("ES"); //--------------------------------------------------------------------------- // Creates a Product object inside the Reaction object ("vcat"). //--------------------------------------------------------------------------- // (Product1) Creates a Product object that references Species "E" in the model. spr = reaction->createProduct(); spr->setSpecies("E"); // (Product2) Creates a Product object that references Species "P" in the model. spr = reaction->createProduct(); spr->setSpecies("P"); //--------------------------------------------------------------------------- // Creates a KineticLaw object inside the Reaction object ("vcat"). //--------------------------------------------------------------------------- kl = reaction->createKineticLaw(); //--------------------------------------------------------------------------- // Sets a math (ASTNode object) to the KineticLaw object. //--------------------------------------------------------------------------- // To create mathematical expressions, one would typically construct // an ASTNode tree as the above example code which creates a math of another // KineticLaw object. Here, to save some space and illustrate another approach // of doing it, we will write out the formula in MathML form and then use a // libSBML convenience function to create the ASTNode tree for us. // (This is a bit dangerous; it's very easy to make mistakes when writing MathML // by hand, so in a real program, we would not really want to do it this way.) string mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" " <apply>" " <times/>" " <ci> cytosol </ci>" " <ci> kcat </ci>" " <ci> ES </ci>" " </apply>" "</math>"; astMath = readMathMLFromString(mathXMLString.c_str()); kl->setMath(astMath); delete astMath; //--------------------------------------------------------------------------- // Creates local Parameter objects inside the KineticLaw object. //--------------------------------------------------------------------------- // Creates a Parameter ("kcat") para = kl->createParameter(); para->setId("kcat"); para->setValue(0.1); para->setUnits("per_second"); // Returns the created SBMLDocument object. // The returned object must be explicitly deleted by the caller, // otherwise a memory leak will happen. return sbmlDoc; }
/** * Save the gene network to an SBML file. If the argument is null, use the network id. * @param filename URL to the file describing the network to load * @throws IOException */ void GeneNetwork::writeSBML(const char *filename) { ofstream data_file(filename); if (!data_file.is_open()) { std::cerr << "Failed to open file " << filename << std::endl; exit(1); } data_file.close(); ::logging::log::emit<Info>() << "Writing file " << filename << ::logging::log::endl; SBMLDocument *sbmlDoc = new SBMLDocument(3, 1); Model *model = sbmlDoc->createModel(); model->setId(id_); //model.getNotes ().add (comment_); // save network description int size = getSize(); Compartment *comp = model->createCompartment(); comp->setId("cell"); comp->setSize(1); std::vector<Species*> all_sp; Species *sp; for (int s=0; s < size; s++) { // save gene as species // species[s] = new Species(nodeIds_.get(s), nodeIds_.get(s)); sp = model->createSpecies(); sp->setCompartment("cell"); sp->setId((nodes_.at(s)).getLabel()); all_sp.push_back(sp); //species[s].setInitialAmount(?); // maybe save the wild-type steady state? //model.addSpecies(species[s]); } // create the void species sp = model->createSpecies(); sp->setCompartment("cell"); sp->setId("_void_"); sp->setInitialAmount(0); sp->setBoundaryCondition(true); sp->setConstant(true); all_sp.push_back(sp); //model.addSpecies(species[size]); // SET SYNTHESIS AND DEGRADATION REACTIONS FOR EVERY GENE for (int i=0; i<size; i++) { //::logging::log::emit<Info>() << ::logging::log::dec << i << //::logging::log::endl; // the ID of gene i // String currentGeneID = nodeIds_.get(i); string currentGeneID = (nodes_.at(i)).getLabel(); // The modifiers (regulators) of gene i std::vector<std::string> inputGenes = (nodes_.at(i)).getInputGenes(); // SYNTHESIS REACTION std::string reactionId = currentGeneID + "_synthesis"; Reaction *reaction = model->createReaction(); KineticLaw *kineticLaw = reaction->createKineticLaw(); SpeciesReference *spr; ModifierSpeciesReference *msr; reaction->setId(reactionId); reaction->setReversible (false); spr = reaction->createReactant(); spr->setSpecies(sp->getId()); spr = reaction->createProduct(); spr->setSpecies((all_sp.at(i))->getId()); std::stringstream ss; ss << inputGenes.size(); //::logging::log::emit<Debug>() << "node = " << nodes_.at(i).getLabel().c_str() << " #inputs = " << ss.str().c_str() << ::logging::log::endl; for (unsigned int r=0; r<inputGenes.size(); r++) {// set gene modifiers // reaction.addModifier(species[inputIndexes.get(r)]); //log.log(Level.INFO, "i = " + size); msr = reaction->createModifier(); msr->setSpecies((all_sp.at(getIndexOfNode(inputGenes.at(r))))->getId()); } //std::vector<RegulatoryModule> modules = (nodes_.at(i)).getRegulatoryModules(); //log.log(Level.INFO, "size = " + modules.size()); std::map<std::string, double> *params = new std::map<std::string, double>(); (nodes_.at(i)).compileParameters(*params); //char buf[256]; //sprintf(buf, "%f", nodes_.at(i).getDelta()); //::logging::log::emit<Info>() << buf << ::logging::log::endl; //::logging::log::emit<Info>() << ::logging::log::dec << nodes_.at(i).getAlpha().size() << // ::logging::log::endl; Parameter *para; // save gene parameters (note, the first param is the degradation rate) std::map<std::string, double>::iterator p = params->begin(); //p++; for (; p!=params->end(); p++) { //if (p == params->begin()) { // p++; // continue; //} //::logging::log::emit<Info>() << p->first.c_str() << // ::logging::log::endl; if (p->first != "delta") { para = kineticLaw->createParameter(); para->setId(p->first); para->setValue(p->second); } } reaction->setKineticLaw(kineticLaw); model->addReaction(reaction); // DEGRADATION REACTION reaction = model->createReaction(); kineticLaw = reaction->createKineticLaw(); reactionId = currentGeneID + "_degradation"; reaction->setId(reactionId); reaction->setReversible(false); spr = reaction->createReactant(); spr->setSpecies((all_sp.at(i))->getId()); spr = reaction->createProduct(); spr->setSpecies(sp->getId()); para = kineticLaw->createParameter(); std::map<std::string,double>::iterator it = params->find("delta"); para->setId(it->first); para->setValue(it->second); reaction->setKineticLaw (kineticLaw); model->addReaction (reaction); } // PRINT FILE SBMLWriter sbmlWriter; sbmlWriter.writeSBML(sbmlDoc, filename); delete sbmlDoc; }