Skip to content

Commit

Permalink
Merge pull request #32 from sys-bio/add-features-fix-bugs
Browse files Browse the repository at this point in the history
Fix Bugs and Add Features
  • Loading branch information
adelhpour authored Dec 17, 2024
2 parents 2cfd718 + d4fbd21 commit c7b9c95
Show file tree
Hide file tree
Showing 20 changed files with 302 additions and 99 deletions.
61 changes: 50 additions & 11 deletions src/bindings/python/ctypes/libsbmlnetwork.py.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ class LibSBMLNetwork:
A wrapper class to use libSBMLNetwork, which is an API to work with the Layout and Render packages of libSBML
"""

def __init__(self, sbml):
def __init__(self, sbml, disable_auto_layout=False):
"""
Initializes the LibSBMLNetwork class by reading an SBML document from the given file name or the given text string

:Parameters:

- sbml: an SBML document in the form of either an SBML file (.xml) directory or an SBML string
- disable_auto_layout (boolean, optional): a boolean (default: False) that determines whether to disable the autolayout algorithm after loading the SBML document
"""

self.sbml_object = None
Expand All @@ -40,7 +41,7 @@ class LibSBMLNetwork:
self.display_compartments_text_label = True
self.display_species_text_label = True
self.display_reactions_text_label = False
self.load(sbml)
self.load(sbml, disable_auto_layout)

def getVersion(self):
"""
Expand All @@ -65,13 +66,14 @@ class LibSBMLNetwork:
lib.c_api_getLibraryCurrentDirectory.restype = ctypes.c_char_p
return ctypes.c_char_p(lib.c_api_getCurrentDirectoryOfLibrary()).value.decode()

def load(self, sbml):
def load(self, sbml, disable_auto_layout=False):
"""
Reads an SBML document from the given file directory or the given text string

:Parameters:

- sbml (string): a string that determines either the name or full pathname of the SBML(.xml) file to be read or a string containing a full SBML model.
- disable_auto_layout (boolean, optional): a boolean (default: False) that determines whether to disable the autolayout algorithm after loading the SBML document

:Returns:

Expand All @@ -81,12 +83,13 @@ class LibSBMLNetwork:
self.sbml_object = lib.c_api_readSBML(str(sbml).encode())
if not self.isSetModel():
raise Exception(f"The SBML document could not be loaded. {sbml} is neither a valid SBML file path nor a valid SBML string.")
if not self._layout_is_specified():
self.autolayout()
self.layout_is_added = True
if not self._render_is_specified():
self.autorender()
self.render_is_added = True
if not disable_auto_layout:
if not self._layout_is_specified():
self.autolayout()
self.layout_is_added = True
if not self._render_is_specified():
self.autorender()
self.render_is_added = True

def save(self, file_name=""):
"""
Expand Down Expand Up @@ -175,6 +178,20 @@ class LibSBMLNetwork:
"""
return lib.c_api_autorender(self.sbml_object, ctypes.c_int(max_num_connected_edges))

def updateReactionCurves(self, layout_index=0):
"""
Updates the curves of the centroid node position of the ReactionGlyphs and the curve of their SpeciesReferenceGlyphs in the Layout object with the given index in the given SBMLDocument

:Parameters:

- layout_index (int, optional): an integer (default: 0) that determines the index of the Layout object in the given SBMLDocument

:Returns:

true on success and false if the curves could not be updated
"""
return lib.c_api_updateReactionCurves(self.sbml_object, layout_index)

def align(self, nodes, alignment="center", ignore_fixed_position_nodes=False):
"""
Aligns the given nodes in the given alignment type form in the given SBMLDocument
Expand Down Expand Up @@ -1317,7 +1334,7 @@ class LibSBMLNetwork:
"""
return lib.c_api_setSpeciesReferenceRole(self.sbml_object, str(reaction_id).encode(), str(role).encode(), reaction_glyph_index, species_reference_index, layout_index)

def getNumSpeciesReferenceAssociatedWithSpecies(self, species_id, reaction_id, reaction_glyph_index = 0):
def getNumSpeciesReferenceAssociatedWithSpecies(self, species_id, reaction_id, reaction_glyph_index = 0, layout_index = 0):
"""
Returns the number of SpeciesReferences associated with the given species_id in the given SBMLDocument

Expand All @@ -1331,7 +1348,7 @@ class LibSBMLNetwork:

an integer that determines the number of SpeciesReferences associated with the given species_id in the given SBMLDocument
"""
return lib.c_api_getNumSpeciesReferenceAssociatedWithSpecies(self.sbml_object, str(species_id).encode(), str(reaction_id).encode(), reaction_glyph_index)
return lib.c_api_getNumSpeciesReferenceAssociatedWithSpecies(self.sbml_object, str(species_id).encode(), str(reaction_id).encode(), reaction_glyph_index, layout_index)

def getSpeciesReferenceIndexAssociatedWithSpecies(self, species_id, reaction_id, reaction_glyph_index = 0, n = 0, layout_index = 0):
"""
Expand Down Expand Up @@ -13028,6 +13045,28 @@ class LibSBMLNetwork:

return list_of_geometric_shapes

def getStoichiometricSpeciesReference(self):
"""
Returns the flag to create a species reference for each stoichiometry in the autolayout algorithm

:Returns:

a boolean that determines whether the autolayout must create a species reference for each stoichiometry or not

"""
return lib.c_api_getStoichiometricSpeciesReference(self.sbml_object)

def setStoichiometricSpeciesReference(self, stoichiometric_species_reference):
"""
Set the flag to create a species reference for each stoichiometry in the autolayout algorithm

:Parameters:

- stoichiometric_species_reference (bool): a boolean that determines whether the autolayout must create a species reference for each stoichiometry or not

"""
return lib.c_api_setStoichiometricSpeciesReference(self.sbml_object, stoichiometric_species_reference)

def getUseNameAsTextLabel(self, layout_index=0):
"""
Returns the flag to use the name of the model entity as the text label of the GraphicalObject associated with the model entity in the layout with the given layout_index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@

class SBMLNetwork(libsbmlnetwork.LibSBMLNetwork):

def __init__(self, sbml=""):
super().__init__(sbml)
def __init__(self, sbml="", disable_autolayout=False):
"""
Initializes the SBMLNetwork object.
:param sbml:
:param disable_autolayout:
"""
super().__init__(sbml, disable_autolayout)

def draw(self, file_name=""):
"""
Expand All @@ -27,14 +32,15 @@ def draw(self, file_name=""):
self.display_reactions_text_label))


def load(sbml):
def load(sbml, disable_autolayout=False):
"""
Loads the SBML model.
:param sbml: The SBML model.
:param disable_autolayout: If True, the autolayout will not be applied.
:return: SBMLNetwork
"""
return SBMLNetwork(sbml)
return SBMLNetwork(sbml, disable_autolayout)



Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def test_use_name_as_text_label(self):
"""
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml)
# default use name as text label is False
# default use name as text label
self.assertEqual(network.getText("S1"), "Species 1")
# set use name as text label to False
network.setUseNameAsTextLabel(False)
Expand Down Expand Up @@ -119,10 +119,13 @@ def test_layout_size(self):
"""
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml)
network.setCanvasWidth(1234.0)
network.setCanvasHeight(1432.0)
self.assertEqual(network.getCanvasWidth(), 1234.0)
self.assertEqual(network.getCanvasHeight(), 1432.0)
network.setCanvasWidth(1000.0)
network.setCanvasHeight(1000.0)
self.assertEqual(network.getCanvasWidth(), 1000.0)
self.assertEqual(network.getCanvasHeight(), 1000.0)
network.autolayout()
self.assertEqual(network.getCanvasWidth(), 1000.0)
self.assertEqual(network.getCanvasHeight(), 1000.0)

def test_align_top(self):
model = """
Expand Down Expand Up @@ -793,6 +796,65 @@ def test_swap_species_glyph_in_reaction(self):
network.setSpeciesGlyphIndexInReactionGlyph("S1", "J2", 2)
self.assertEqual(network.getSpeciesGlyphIndex("S1", "J1"), 2)

def test_species_reference_index_associated_with_species(self):
model = '''
J0: S1 -> S2;
'''
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml)
self.assertEqual(network.getSpeciesReferenceIndexAssociatedWithSpecies("S1", "J0"), 0)
self.assertEqual(network.getSpeciesReferenceIndexAssociatedWithSpecies("S2", "J0"), 1)

def test_set_stoichiometric_species_reference(self):
model = '''
J0: 100000 S1 -> 200000 S2;
'''
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml, disable_autolayout=True)
# set stoichiometric species reference
network.setStoichiometricSpeciesReference(False)
network.autolayout()
self.assertEqual(network.getNumSpeciesReferenceAssociatedWithSpecies("S1", "J0"), 1)

def test_disable_autolayout_at_load(self):
model = '''
S1 -> S2;
'''
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml, disable_autolayout=True)
self.assertEqual(network.getNumLayouts(), 0)
self.assertEqual(network.getNumGlobalRenderInformation(), 0)
self.assertEqual(network.getNumLocalRenderInformation(), 0)
network.autolayout()
self.assertEqual(network.getNumLayouts(), 1)
self.assertEqual(network.getNumGlobalRenderInformation(), 1)
self.assertEqual(network.getNumLocalRenderInformation(), 1)

def test_set_colors_of_a_group_of_graphical_objects(self):
model = '''
S1 -> S2;
'''
sbml = te.loada(model).getSBML()
network = sbmlnetwork.SBMLNetwork(sbml)
network.setCompartmentsBorderColor("#FF0000")
network.setCompartmentsFontColor("#A52A2A")
network.setSpeciesBorderColor("#00FF00")
network.setSpeciesFontColor("#800080")
network.setReactionsLineColor("#0000FF")
network.setReactionsFontColor("#FFC0CB")
network.setCompartmentsFillColor("#FFFF00")
network.setSpeciesFillColor("#FFA500")
network.setReactionsFillColor("#FF00FF")
self.assertEqual(network.getCompartmentsBorderColor(), "red")
self.assertEqual(network.getCompartmentsFontColor(), "brown")
self.assertEqual(network.getSpeciesBorderColor(), "lime")
self.assertEqual(network.getSpeciesFontColor(), "purple")
self.assertEqual(network.getReactionsLineColor(), "blue")
self.assertEqual(network.getReactionsFontColor(), "pink")
self.assertEqual(network.getCompartmentsFillColor(), "yellow")
self.assertEqual(network.getSpeciesFillColor(), "orange")
self.assertEqual(network.getReactionsFillColor(), "fuchsia")

@staticmethod
def _get_max_position_y(network, species_list):
max_position_y = -math.inf
Expand Down
12 changes: 12 additions & 0 deletions src/c_api/libsbmlnetwork_c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE {
return autorender(document, maxNumConnectedEdges);
}

int c_api_updateReactionCurves(SBMLDocument* document, const int layoutIndex) {
return updateLayoutCurves(document, getLayout(document, layoutIndex));
}

int c_api_align(SBMLDocument* document, const char ***nodes, const int nodesSize, const char* alignment, bool ignorefixedPositionNodes) {
std::set<std::pair<std::string, int> > nodesSet = std::set<std::pair<std::string, int> >();
if (nodes) {
Expand Down Expand Up @@ -185,6 +189,14 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE {
return createDefaultLayoutLocations(document, maxNumConnectedEdges, resetFixedPositionElements, fixedPositionNodesSet);
}

bool c_api_getStoichiometricSpeciesReference(SBMLDocument* document) {
return getStoichiometricSpeciesReference(document);
}

int c_api_setStoichiometricSpeciesReference(SBMLDocument* document, bool stoichiometricSpeciesReference) {
return setStoichiometricSpeciesReference(document, stoichiometricSpeciesReference);
}

bool c_api_getUseNameAsTextLabel(SBMLDocument* document, int layoutIndex) {
return getUseNameAsTextLabel(document, layoutIndex);
}
Expand Down
30 changes: 29 additions & 1 deletion src/c_api/libsbmlnetwork_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE {
/// @return integer value indicating success/failure of the function.
LIBSBMLNETWORK_EXTERN int c_api_autorender(SBMLDocument *document, const int maxNumConnectedEdges = 3);

/// @brief Updates the curves of the centroid node position of the ReactionGlyphs and the curve of their SpeciesReferenceGlyphs in the Layout object with the given index in the given SBMLDocument.
/// @param document a pointer to the SBMLDocument object.
/// @param layoutIndex the index number of the Layout to return.
/// @return integer value indicating success/failure of the function.
LIBSBMLNETWORK_EXTERN int c_api_updateReactionCurves(SBMLDocument* document, const int layoutIndex = 0);

/// @brief Align the nodes position in the SBML document in the given alignment type.
/// @param document a pointer to the SBMLDocument object.
/// @param nodes an array of strings containing the ids of the nodes and their associated graphical objects that should be aligned.
Expand Down Expand Up @@ -231,7 +237,29 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE {
LIBSBMLNETWORK_EXTERN int c_api_createDefaultLayoutLocations(SBMLDocument* document, const int maxNumConnectedEdges = 3,
bool resetFixedPositionElements = false, const char*** fixedPositionNodeIds = NULL, const int fixedPositionNodesSize = 0);

LIBSBMLNETWORK_EXTERN int c_api_setUseNameAsTextLabel(SBMLDocument* document, bool useNameAsTextLabel, int layoutIndex);
/// @brief Returns the value of the option to generate stoichiometric species reference in the autolayout algorithm.
/// @param document a pointer to the SBMLDocument object.
/// @return the value of the option to generate stoichiometric species reference in the autolayout algorithm.
LIBSBMLNETWORK_EXTERN bool c_api_getStoichiometricSpeciesReference(SBMLDocument* document);

/// @brief Sets the value of the option to generate stoichiometric species reference in the autolayout algorithm.
/// @param document a pointer to the SBMLDocument object.
/// @param stoichiometricSpeciesReference the value of the option to generate stoichiometric species reference in the autolayout algorithm.
/// @return integer value indicating success/failure of the function.
LIBSBMLNETWORK_EXTERN int c_api_setStoichiometricSpeciesReference(SBMLDocument* document, bool stoichiometricSpeciesReference);

/// @brief Returns the option to use the name of the model entity as the text label of the GraphicalObject associated with the model entities in the Layout object with the given index in the ListOfLayouts of the SBMLDocument.
/// @param document a pointer to the SBMLDocument object.
/// @param layoutIndex the index number of the Layout to return.
/// @return the option to use the name of the model entity as the text label of the GraphicalObject associated with the model entities.
LIBSBMLNETWORK_EXTERN bool c_api_getUseNameAsTextLabel(SBMLDocument* document, int layoutIndex = 0);

/// @brief Sets the option to use the name of the model entity as the text label of the GraphicalObject associated with the model entities in the Layout object with the given index in the ListOfLayouts of the SBMLDocument.
/// @param document a pointer to the SBMLDocument object.
/// @param useNameAsTextLabel the option to use the name of the model entity as the text label of the GraphicalObject associated with the model entities.
/// @param layoutIndex the index number of the Layout to return.
/// @return integer value indicating success/failure of the function.
LIBSBMLNETWORK_EXTERN int c_api_setUseNameAsTextLabel(SBMLDocument* document, bool useNameAsTextLabel, int layoutIndex = 0);

/// @brief Create an alias SpeciesGlyph object for Species with the given id and connect all the SpeciesReferences in the ReactionGlyph object with the given id and index that contain Species as a participant to the alias SpeciesGlyph in the Layout object with the given index in the ListOfLayouts of the SBMLDocument.
/// @param document a pointer to the SBMLDocument object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE {
speciesGlyphAliasSpeciesGlyphIds[speciesGlyph->getId()]);
if (connectedSpeciesGlyph) {
speciesGlyphAliasSpeciesGlyphIds[speciesGlyph->getId()] = connectedSpeciesGlyph->getId();
int stoichiometry = getStoichiometryAsInteger(
int stoichiometry = getStoichiometryAsInteger(layout,
findSpeciesReference(document->getModel(), layout, referenceReactionGlyph, speciesGlyph));
for (unsigned int stoichiometryIndex = 0; stoichiometryIndex < stoichiometry; stoichiometryIndex++)
alias_element_createAliasSpeciesReferenceGlyph(reactionGlyph, speciesReferenceGlyph,
Expand Down
Loading

0 comments on commit c7b9c95

Please sign in to comment.