Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -454,21 +454,21 @@ jobs:
shell: bash
run: |
cd ${RUNNER_WORKSPACE}/build-roadrunner
ctest --output-on-failure --verbose --extra-verbose --progress --exclude-regex python_tests
ctest --output-on-failure --verbose --extra-verbose --progress --exclude-regex ython

- name: Run C RoadRunner tests (Ubuntu; skip plugins)
if: matrix.platform.build_type == 'Release' && matrix.build_tests == 'ON' && matrix.platform.os_type == 'ubuntu'
shell: bash
run: |
cd ${RUNNER_WORKSPACE}/build-roadrunner
ctest --output-on-failure --verbose --extra-verbose --progress --exclude-regex python_tests --exclude-regex Plugin
ctest --output-on-failure --verbose --extra-verbose --progress --exclude-regex "ython|Plugin"

- name: Run Python Roadrunner tests (first Python version)
if: matrix.platform.build_python == 'ON' && matrix.build_tests == 'ON'
shell: bash
run: |
cd ${RUNNER_WORKSPACE}/build-roadrunner
ctest -C ${{ matrix.platform.build_type }} --output-on-failure --verbose --extra-verbose --progress --tests-regex python_tests
ctest -C ${{ matrix.platform.build_type }} --output-on-failure --verbose --extra-verbose --progress --tests-regex ython

- name: Save roadrunner version
shell: bash
Expand Down Expand Up @@ -591,7 +591,7 @@ jobs:
shell: bash
run: |
cd ${RUNNER_WORKSPACE}/build-roadrunner
ctest -C ${{ matrix.platform.build_type }} --output-on-failure --verbose --extra-verbose --progress --tests-regex python_tests
ctest -C ${{ matrix.platform.build_type }} --output-on-failure --verbose --extra-verbose --progress --tests-regex ython


- name: Create fourth Python wheel artifacts and rename
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16)

set(ROADRUNNER_VERSION_MAJOR 2)
set(ROADRUNNER_VERSION_MINOR 9)
set(ROADRUNNER_VERSION_PATCH 1)
set(ROADRUNNER_VERSION_PATCH 2)

set(ROADRUNNER_VERSION "${ROADRUNNER_VERSION_MAJOR}.${ROADRUNNER_VERSION_MINOR}.${ROADRUNNER_VERSION_PATCH}")

Expand Down
21 changes: 17 additions & 4 deletions source/llvm/LLVMExecutableModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,10 @@ double LLVMExecutableModel::getValue(const std::string& id)
case SelectionRecord::INITIAL_GLOBAL_PARAMETER:
getGlobalParameterInitValues(1, &index, &result);
break;
case SelectionRecord::STOICHIOMETRY:
case SelectionRecord::INITIAL_STOICHIOMETRY:
result = getStoichiometry(index);
break;
case SelectionRecord::EVENT:
{
bool trigger = getEventTrigger(index);
Expand Down Expand Up @@ -1634,10 +1638,19 @@ const rr::SelectionRecord& LLVMExecutableModel::getSelection(const std::string&
}
break;
case SelectionRecord::STOICHIOMETRY:
sel.index = getStoichiometryIndex(sel.p1, sel.p2);
if (sel.index == -1) {
throw LLVMException("Invalid id '" + str + "': could not find a species with the ID '" + sel.p1 + "', and/or a reaction with the ID '" + sel.p2 + "'");
break;
if (sel.p2.empty()) {
sel.index = getStoichiometryIndex(sel.p1);
if (sel.index == -1) {
throw LLVMException("Invalid id '" + str + "': could not find a stoichiometry with the ID '" + sel.p1 + "'.");
break;
}
}
else {
sel.index = getStoichiometryIndex(sel.p1, sel.p2);
if (sel.index == -1) {
throw LLVMException("Invalid id '" + str + "': could not find a species with the ID '" + sel.p1 + "', and/or a reaction with the ID '" + sel.p2 + "'");
break;
}
}

break;
Expand Down
31 changes: 19 additions & 12 deletions source/rrRoadRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1353,12 +1353,7 @@ namespace rr {
break;
case SelectionRecord::STOICHIOMETRY:
case SelectionRecord::INITIAL_STOICHIOMETRY: {
// in case it is entered in the form of stoich(SpeciesId, ReactionId)
if (impl->model->getFloatingSpeciesIndex(record.p1) != -1 && impl->model->getReactionIndex(record.p2) != -1)
dResult = impl->model->getStoichiometry(impl->model->getStoichiometryIndex(record.p1, record.p2));
// in case it is entered in the form of a stoichiometry parameter
else
dResult = impl->model->getStoichiometry(impl->model->getStoichiometryIndex(record.p1));
dResult = impl->model->getStoichiometry(record.index);
break;
}
case SelectionRecord::TIME:
Expand Down Expand Up @@ -4914,14 +4909,26 @@ namespace rr {
}
break;
case SelectionRecord::STOICHIOMETRY:
if (impl->model->getFloatingSpeciesIndex(sel.p1) >= 0) {
if (impl->model->getReactionIndex(sel.p2) >= 0) {
break;
if (sel.p2.empty()) {
if (impl->model->getStoichiometryIndex(sel.p1) < 0) {
throw Exception("The id '" + sel.p1 + "' is not the id of a stoichiometry (speciesReference).");
}
break;
}
else {
if (impl->model->getFloatingSpeciesIndex(sel.p1) >= 0) {
if (impl->model->getReactionIndex(sel.p2) >= 0) {
sel.index = impl->model->getStoichiometryIndex(sel.p1, sel.p2);
if (sel.index < 0) {
throw Exception("The species id '" + sel.p1 + "' and reaction id '" + sel.p2 + "' does not lead to a valid stoichiometry.");
}
break;
} else {
throw Exception("second argument to stoich '" + sel.p2 + "' is not a reaction id.");
}
} else {
throw Exception("second argument to stoich '" + sel.p2 + "' is not a reaction id.");
throw Exception("first argument to stoich '" + sel.p1 + "' is not a floating species id.");
}
} else {
throw Exception("first argument to stoich '" + sel.p1 + "' is not a floating species id.");
}
case SelectionRecord::INITIAL_CONCENTRATION:
if ((sel.index = impl->model->getFloatingSpeciesIndex(sel.p1)) >= 0) {
Expand Down
2 changes: 1 addition & 1 deletion test/cxx_api_tests/SelectionRecordTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ TEST_F(SelectionRecordTests, STOICHIOMETRY){
SelectionRecord record = rr.createSelection("stoich(S1, _J1)");
EXPECT_EQ(record.selectionType, SelectionRecord::STOICHIOMETRY);
EXPECT_STREQ(record.to_string().c_str(), "stoich(S1, _J1)");
EXPECT_EQ(record.index, -1);
EXPECT_EQ(record.index, 3);
EXPECT_EQ(record.p1, "S1");
EXPECT_EQ(record.p2, "_J1");
delete testModel;
Expand Down
45 changes: 45 additions & 0 deletions test/python/named_stoic_in_kinetic_law.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by libAntimony version v3.1.2 with libSBML version 5.21.1. -->
<sbml xmlns="http://www.sbml.org/sbml/level3/version2/core" xmlns:comp="http://www.sbml.org/sbml/level3/version1/comp/version1" level="3" version="2" comp:required="true">
<model metaid="__main" id="__main">
<listOfCompartments>
<compartment sboTerm="SBO:0000410" id="default_compartment" spatialDimensions="3" size="1" constant="true"/>
</listOfCompartments>
<listOfSpecies>
<species id="A" compartment="default_compartment" initialConcentration="1" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
<species id="B" compartment="default_compartment" initialConcentration="7" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
<species id="C" compartment="default_compartment" initialConcentration="0" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
<species id="D" compartment="default_compartment" initialConcentration="0" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
</listOfSpecies>
<listOfParameters>
<parameter id="k1" value="0.1" constant="true"/>
<parameter id="k2" value="0.04" constant="true"/>
</listOfParameters>
<listOfReactions>
<reaction id="J0" reversible="true">
<listOfReactants>
<speciesReference species="A" stoichiometry="1" constant="true"/>
<speciesReference id="n" species="B" stoichiometry="1" constant="true"/>
</listOfReactants>
<listOfProducts>
<speciesReference id="m" species="C" stoichiometry="2" constant="true"/>
<speciesReference id="q" species="D" stoichiometry="3" constant="true"/>
</listOfProducts>
<kineticLaw>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<apply>
<times/>
<apply>
<plus/>
<ci> n </ci>
<ci> m </ci>
<ci> q </ci>
</apply>
<ci> A </ci>
</apply>
</math>
</kineticLaw>
</reaction>
</listOfReactions>
</model>
</sbml>
17 changes: 17 additions & 0 deletions test/python/test_python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,23 @@ def test_getFullStoichiometryMatrix(self):

def test_getGlobalParameterByName(self):
self.assertEqual(self.rr.getGlobalParameterByName("kf"), 0.1)

def test_getSetNamedStoichiometries(self):
rr = RoadRunner("named_stoic_in_kinetic_law.xml")
self.assertEqual(rr.n, 1)
self.assertEqual(rr.m, 2)
self.assertEqual(rr.q, 3)
self.assertEqual(rr['q'], 3)
self.assertEqual(rr.model['q'], 3)
self.assertEqual(rr.getValue('q'), 3)
rr.n = 3
rr.m = 5
rr.q = 7
self.assertEqual(rr['n'], 3)
self.assertEqual(rr['m'], 5)
self.assertEqual(rr['q'], 7)
self.assertEqual(rr.model['q'], 7)
self.assertEqual(rr.getValue('q'), 7)

@unittest.skip("No way to use this method from Python - it "
"requires an out parameter as input")
Expand Down
50 changes: 49 additions & 1 deletion test/sbml_features/named_stoich.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <filesystem>
#include "RoadRunnerTest.h"
#include "llvm/LLVMException.h"
#include "llvm/LLVMExecutableModel.h"

using namespace testing;
using namespace rr;
Expand Down Expand Up @@ -85,7 +86,21 @@ TEST_F(SBMLFeatures, named_stoich_init_value) {
}


TEST_F(SBMLFeatures, variable_named_stoich) {
TEST_F(SBMLFeatures, named_stoich_values) {
rr::RoadRunner rr((SBMLFeaturesDir / "named_stoic_in_kinetic_law.xml").string());
rr.setValue("n", 3);
rr.setValue("m", 5);
rr.setValue("q", 7);
EXPECT_EQ(rr.getModel()->getValue("n"), 3.0);
EXPECT_EQ(rr.getModel()->getValue("m"), 5.0);
EXPECT_EQ(rr.getModel()->getValue("q"), 7.0);
EXPECT_EQ(rr.getModel()->getValue("init(n)"), 3.0);
EXPECT_EQ(rr.getModel()->getValue("init(m)"), 5.0);
EXPECT_EQ(rr.getModel()->getValue("init(q)"), 7.0);
}


TEST_F(SBMLFeatures, no_variable_named_stoich) {
rr::RoadRunner rr((SBMLFeaturesDir / "named_stoic_in_kinetic_law.xml").string());
EXPECT_THROW(rr.addAssignmentRule("n", "5", true), rrllvm::LLVMException);

Expand All @@ -94,3 +109,36 @@ TEST_F(SBMLFeatures, variable_named_stoich) {
}


TEST_F(SBMLFeatures, named_stoich_selectors) {
rr::RoadRunner rr((SBMLFeaturesDir / "named_stoic_in_kinetic_law.xml").string());
SelectionRecord record = rr.createSelection("n");
EXPECT_EQ(record.selectionType, SelectionRecord::STOICHIOMETRY);
EXPECT_STREQ(record.to_string().c_str(), "n");
EXPECT_EQ(record.index, 1);
EXPECT_EQ(record.p1, "n");
EXPECT_EQ(record.p2, "");

record = rr.createSelection("stoich(A, J0)");
EXPECT_EQ(record.selectionType, SelectionRecord::STOICHIOMETRY);
EXPECT_STREQ(record.to_string().c_str(), "stoich(A, J0)");
EXPECT_EQ(record.index, 0);
EXPECT_EQ(record.p1, "A");
EXPECT_EQ(record.p2, "J0");
}


TEST_F(SBMLFeatures, get_named_stoich_value_from_model) {
rr::RoadRunner rr((SBMLFeaturesDir / "named_stoic_in_kinetic_law.xml").string());
ExecutableModel* em = rr.getModel();
rrllvm::LLVMExecutableModel* llem = static_cast<rrllvm::LLVMExecutableModel*>(em);

EXPECT_EQ(llem->getValue("n"), 1);
llem->setValue("n", 3);
EXPECT_EQ(llem->getValue("n"), 3);

EXPECT_EQ(llem->getValue("stoich(A, J0)"), 1);
llem->setValue("stoich(A, J0)", 5);
EXPECT_EQ(llem->getValue("stoich(A, J0)"), 5);
}


8 changes: 8 additions & 0 deletions wrappers/Python/roadrunner/roadrunner.i
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,10 @@ namespace std { class ostream{}; }
for s in model.getGlobalParameterIds() + model.getCompartmentIds() + model.getReactionIds() + model.getConservedMoietyIds():
makeProperty(s, s)

for s in model.getStoichiometryIds():
if "(" not in s:
makeProperty(s, s)

def __getstate__(self):
return self.saveStateS()

Expand Down Expand Up @@ -2498,6 +2502,10 @@ namespace std { class ostream{}; }
return rr_ExecutableModel_getIds($self, rr::SelectionRecord::REACTION_RATE);
}

PyObject *getStoichiometryIds() {
return rr_ExecutableModel_getIds($self, rr::SelectionRecord::STOICHIOMETRY);
}

PyObject *getFloatingSpeciesInitAmountIds() {
return rr_ExecutableModel_getIds($self, rr::SelectionRecord::INITIAL_FLOATING_AMOUNT);
}
Expand Down
17 changes: 15 additions & 2 deletions wrappers/Python/roadrunner/rr_docstrings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,22 @@ ExecutableModel.getConservedMoietyIds([index])
Returns a vector of conserved moiety identifier symbols.


:param index: A array of compartment indices indicating which compartment ids to return.
:param index: A array of conserved moiety indices indicating which conserved moiety ids to return.
:type index: None or numpy.ndarray
:returns: a list of compartment ids.
:returns: a list of conserved moiety ids.
";



%feature("docstring") rr::ExecutableModel::getStoichiometryIds "
ExecutableModel.getStoichiometryIds([index])

Returns a vector of stoichiometry identifier symbols.


:param index: A array of stoichiometry indices indicating which stoichiometry ids to return.
:type index: None or numpy.ndarray
:returns: a list of stoichiometry ids.
";


Expand Down
Loading