From f5b90ccd2105c72d72c407737d7cf899e9ba7687 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 11:45:34 -0800 Subject: [PATCH 01/13] - The bug with user-set canvas dimensions vanishing after calling autolayout fixed - A test is modified to check for it --- .../tests/test_with_specific_models.py | 3 + .../autolayout/libsbmlnetwork_autolayout.cpp | 100 +++++++++--------- .../autolayout/libsbmlnetwork_autolayout.h | 14 ++- 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index ffdcf06..8aa19b3 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -123,6 +123,9 @@ def test_layout_size(self): network.setCanvasHeight(1432.0) self.assertEqual(network.getCanvasWidth(), 1234.0) self.assertEqual(network.getCanvasHeight(), 1432.0) + network.autolayout() + self.assertEqual(network.getCanvasWidth(), 1234.0) + self.assertEqual(network.getCanvasHeight(), 1432.0) def test_align_top(self): model = """ diff --git a/src/features/autolayout/libsbmlnetwork_autolayout.cpp b/src/features/autolayout/libsbmlnetwork_autolayout.cpp index b17f9d7..551d825 100755 --- a/src/features/autolayout/libsbmlnetwork_autolayout.cpp +++ b/src/features/autolayout/libsbmlnetwork_autolayout.cpp @@ -33,15 +33,9 @@ void autolayout_locateGlyphs(Model *model, Layout *layout) { autolayout_updateCompartmentsExtents(model, layout); autolayout_updateLayoutDimensions(layout); delete autoLayoutAlgorithm; - if (!autolayout_adjustLayoutDimensions(layout)) { - if (autolayout_autolayoutMayStillConverge(layout)) { - autolayout_updateGravity(layout); - autolayout_updateStiffness(layout); - autolayout_locateGlyphs(model, layout); - } - else - error_log_addErrorToLog(layout, "Auto-layout fails to converge with the given layout dimensions. Please adjust layout width and height and try again."); - } + if (!autolayout_adjustLayoutDimensions(layout)) + autolayout_reiterateLocateGlyphs(model, layout); + autolayout_resetNumberOfAutoLayoutParametersResets(layout); } void autolayout_locateReactions(Model *model, Layout *layout) { @@ -64,11 +58,29 @@ void autolayout_locateReactions(Model *model, Layout *layout) { delete autoLayoutAlgorithm; } +void autolayout_reiterateLocateGlyphs(Model *model, Layout *layout) { + if (autolayout_isGravityValueAcceptable(layout)) { + autolayout_updateGravity(layout); + autolayout_updateStiffness(layout); + autolayout_locateGlyphs(model, layout); + } + else if (autolayout_getNumberOfAutoLayoutParametersResets(layout) < 5) { + autolayout_resetAutoLayoutParameters(layout); + autolayout_locateGlyphs(model, layout); + } + else + error_log_addErrorToLog(layout, "Auto-layout fails to converge with the given layout dimensions. Please adjust layout width and height and try again."); +} + +void autolayout_resetNumberOfAutoLayoutParametersResets(Layout *layout) { + LIBSBMLNETWORK_CPP_NAMESPACE::user_data_setUserData(layout, "number_of_auto_layout_parameters_resets", "0"); +} + const double autolayout_getStiffness(Layout *layout) { std::string stiffness = LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout, "stiffness"); if (stiffness.empty()) { - autolayout_setStiffness(layout, 10.0); - return 10.0; + stiffness = "10.0"; + autolayout_setStiffness(layout, stod(stiffness)); } return std::stod(stiffness); @@ -89,8 +101,8 @@ double autolayout_getStiffnessAdjustmentFactor(Layout *layout) { const double autolayout_getGravity(Layout *layout) { std::string gravity = LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout, "gravity"); if (gravity.empty()) { - autolayout_setGravity(layout, 15.0); - return 15.0; + gravity = "15.0"; + autolayout_setGravity(layout, std::stod(gravity)); } return std::stod(gravity); @@ -110,36 +122,32 @@ double autolayout_getGravityAdjustmentFactor(Layout *layout) { double autolayout_getCurrentDimensionToDesiredDimensionRatio(Layout *layout) { double desiredWidth = autolayout_getLayoutDimensionsDesiredWidth(layout); + double widthRatio = layout->getDimensions()->width() / desiredWidth; double desiredHeight = autolayout_getLayoutDimensionsDesiredHeight(layout); - if (layout->getDimensions()->width() < desiredWidth || layout->getDimensions()->height() < desiredHeight) { - double widthRatio = layout->getDimensions()->width() / desiredWidth; - double heightRatio = layout->getDimensions()->height() / desiredHeight; - return std::sqrt(widthRatio * widthRatio + heightRatio * heightRatio); - } - else if (layout->getDimensions()->width() > desiredWidth || layout->getDimensions()->height() > desiredHeight) { - double widthRatio = layout->getDimensions()->width() / desiredWidth; - double heightRatio = layout->getDimensions()->height() / desiredHeight; - return std::sqrt(widthRatio * widthRatio + heightRatio * heightRatio); - } - - return 1.0; + double heightRatio = layout->getDimensions()->height() / desiredHeight; + return std::sqrt(0.5 * (widthRatio * widthRatio + heightRatio * heightRatio)); } double autolayout_getDesiredDimensionToCurrentDimensionRatio(Layout *layout) { double desiredWidth = autolayout_getLayoutDimensionsDesiredWidth(layout); + double widthRatio = desiredWidth / layout->getDimensions()->width(); double desiredHeight = autolayout_getLayoutDimensionsDesiredHeight(layout); - if (layout->getDimensions()->width() < desiredWidth || layout->getDimensions()->height() < desiredHeight) { - double widthRatio = desiredWidth / layout->getDimensions()->width(); - double heightRatio = desiredHeight / layout->getDimensions()->height(); - return std::sqrt(widthRatio * widthRatio + heightRatio * heightRatio); - } - else if (layout->getDimensions()->width() > desiredWidth || layout->getDimensions()->height() > desiredHeight) { - double widthRatio = desiredWidth / layout->getDimensions()->width(); - double heightRatio = desiredHeight / layout->getDimensions()->height(); - return std::sqrt(widthRatio * widthRatio + heightRatio * heightRatio); - } + double heightRatio = desiredHeight / layout->getDimensions()->height(); + return std::sqrt(0.5 * (widthRatio * widthRatio + heightRatio * heightRatio)); +} - return 1.0; +void autolayout_resetAutoLayoutParameters(Layout *layout) { + autolayout_setStiffness(layout, 10.0); + autolayout_setGravity(layout, 15.0); + LIBSBMLNETWORK_CPP_NAMESPACE::user_data_setUserData(layout, "number_of_auto_layout_parameters_resets", std::to_string(autolayout_getNumberOfAutoLayoutParametersResets(layout) + 1)); +} + +const int autolayout_getNumberOfAutoLayoutParametersResets(Layout *layout) { + std::string numberOfResets = LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout, "number_of_auto_layout_parameters_resets"); + if (!numberOfResets.empty()) + return std::stoi(numberOfResets); + + return 0; } void autolayout_randomizeGlyphsLocations(Model *model, Layout *layout) { @@ -336,9 +344,9 @@ const bool autolayout_adjustLayoutDimensions(Layout *layout) { double widthGap = desiredWidth - layout->getDimensions()->width(); double desiredHeight = autolayout_getLayoutDimensionsDesiredHeight(layout); double heightGap = desiredHeight - layout->getDimensions()->height(); - if (widthGap <= 0.1 * desiredWidth && heightGap <= 0.1 * desiredHeight) { - autolayout_setLayoutDimensionsDesiredWidth(layout, layout->getDimensions()->width()); - autolayout_setLayoutDimensionsDesiredHeight(layout, layout->getDimensions()->height()); + if (widthGap >= 0.0 && widthGap <= 0.05 * desiredWidth && heightGap >= 0.0 && heightGap <= 0.05 * desiredHeight) { + layout->getDimensions()->setWidth(desiredWidth); + layout->getDimensions()->setHeight(desiredHeight); return true; } @@ -353,11 +361,6 @@ const double autolayout_getLayoutDimensionsDesiredWidth(Layout *layout) {; return layout->getDimensions()->width(); } -void autolayout_setLayoutDimensionsDesiredWidth(Layout *layout, const double &width) { - if (!LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout->getDimensions(), "width").empty()) - LIBSBMLNETWORK_CPP_NAMESPACE::user_data_setUserData(layout->getDimensions(), "width", std::to_string(width)); -} - const double autolayout_getLayoutDimensionsDesiredHeight(Layout *layout) { std::string presetHeight = LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout->getDimensions(), "height"); if (!presetHeight.empty()) @@ -366,13 +369,8 @@ const double autolayout_getLayoutDimensionsDesiredHeight(Layout *layout) { return layout->getDimensions()->height(); } -void autolayout_setLayoutDimensionsDesiredHeight(Layout *layout, const double &height) { - if (!LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout->getDimensions(), "height").empty()) - LIBSBMLNETWORK_CPP_NAMESPACE::user_data_setUserData(layout->getDimensions(), "height", std::to_string(height)); -} - -const bool autolayout_autolayoutMayStillConverge(Layout *layout) { - if (autolayout_getGravity(layout) > 1.0) +const bool autolayout_isGravityValueAcceptable(Layout *layout) { + if (autolayout_getGravity(layout) > 0.1) return true; return false; diff --git a/src/features/autolayout/libsbmlnetwork_autolayout.h b/src/features/autolayout/libsbmlnetwork_autolayout.h index e7c0267..806f9ca 100755 --- a/src/features/autolayout/libsbmlnetwork_autolayout.h +++ b/src/features/autolayout/libsbmlnetwork_autolayout.h @@ -14,6 +14,10 @@ void autolayout_locateGlyphs(Model* model, Layout* layout); void autolayout_locateReactions(Model *model, Layout *layout); +void autolayout_reiterateLocateGlyphs(Model *model, Layout *layout); + +void autolayout_resetNumberOfAutoLayoutParametersResets(Layout *layout); + const double autolayout_getStiffness(Layout *layout); void autolayout_setStiffness(Layout *layout, const double& stiffness); @@ -34,6 +38,10 @@ double autolayout_getCurrentDimensionToDesiredDimensionRatio(Layout *layout); double autolayout_getDesiredDimensionToCurrentDimensionRatio(Layout *layout); +void autolayout_resetAutoLayoutParameters(Layout *layout); + +const int autolayout_getNumberOfAutoLayoutParametersResets(Layout *layout); + void autolayout_randomizeGlyphsLocations(Model* model, Layout* layout); void autolayout_randomizeSpeciesGlyphsLocations(Model* model, Layout* layout, const double& canvasWidth, const double& canvasHeight); @@ -66,13 +74,9 @@ const bool autolayout_adjustLayoutDimensions(Layout *layout); const double autolayout_getLayoutDimensionsDesiredWidth(Layout *layout); -void autolayout_setLayoutDimensionsDesiredWidth(Layout *layout, const double& width); - const double autolayout_getLayoutDimensionsDesiredHeight(Layout *layout); -void autolayout_setLayoutDimensionsDesiredHeight(Layout *layout, const double& height); - -const bool autolayout_autolayoutMayStillConverge(Layout *layout); +const bool autolayout_isGravityValueAcceptable(Layout *layout); void autolayout_extractExtents(Layout* layout, double &maxX, double &maxY); From e461c4267571f887445a63219a07976fbe77e009 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 11:47:17 -0800 Subject: [PATCH 02/13] - minor fix --- src/features/autolayout/libsbmlnetwork_autolayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/autolayout/libsbmlnetwork_autolayout.cpp b/src/features/autolayout/libsbmlnetwork_autolayout.cpp index 551d825..836e70b 100755 --- a/src/features/autolayout/libsbmlnetwork_autolayout.cpp +++ b/src/features/autolayout/libsbmlnetwork_autolayout.cpp @@ -344,7 +344,7 @@ const bool autolayout_adjustLayoutDimensions(Layout *layout) { double widthGap = desiredWidth - layout->getDimensions()->width(); double desiredHeight = autolayout_getLayoutDimensionsDesiredHeight(layout); double heightGap = desiredHeight - layout->getDimensions()->height(); - if (widthGap >= 0.0 && widthGap <= 0.05 * desiredWidth && heightGap >= 0.0 && heightGap <= 0.05 * desiredHeight) { + if (widthGap >= 0.0 && widthGap <= 0.1 * desiredWidth && heightGap >= 0.0 && heightGap <= 0.1 * desiredHeight) { layout->getDimensions()->setWidth(desiredWidth); layout->getDimensions()->setHeight(desiredHeight); return true; From e472b888e22008ab856b40e6dcd5d340e37312ab Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 17:22:02 -0800 Subject: [PATCH 03/13] the bug with 'getNumSpeciesReferenceAssociatedWithSpecies' function not having 'layout_index' parameter on the Python api is fixed --- src/bindings/python/ctypes/libsbmlnetwork.py.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake index b8875e2..310f403 100644 --- a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake +++ b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake @@ -1317,7 +1317,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 @@ -1331,7 +1331,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): """ From fd2855d8dacfc5dbec7a19ab913e72be7caecf81 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 17:33:18 -0800 Subject: [PATCH 04/13] The test for 'getNumSpeciesReferenceAssociatedWithSpecies' function is added --- .../sbmlnetwork/tests/test_with_specific_models.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index 8aa19b3..dfe63c9 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -796,6 +796,15 @@ 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) + @staticmethod def _get_max_position_y(network, species_list): max_position_y = -math.inf From 3d9484146785d9543c0a13aaa9d0daa99ecfe70e Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 19:23:57 -0800 Subject: [PATCH 05/13] - the option to set whether to disable the autolayout while loading or not is added - the option to turn stoichiometric species references on and off is added - tests are added for the newly added features --- .../python/ctypes/libsbmlnetwork.py.cmake | 43 +++++++++++++++---- .../src/sbmlnetwork/sbmlnetwork.py | 14 ++++-- .../tests/test_with_specific_models.py | 33 +++++++++++++- src/c_api/libsbmlnetwork_c_api.cpp | 8 ++++ src/c_api/libsbmlnetwork_c_api.h | 24 ++++++++++- .../libsbmlnetwork_alias_reaction.cpp | 2 +- .../libsbmlnetwork_set_layout_features.cpp | 6 ++- .../libsbmlnetwork_update_curves.cpp | 2 + .../user_data/libsbmlnetwork_user_data.cpp | 15 +++++++ .../user_data/libsbmlnetwork_user_data.h | 2 + src/libsbmlnetwork_layout_helpers.cpp | 8 ++-- src/libsbmlnetwork_layout_helpers.h | 2 +- src/libsbmlnetwork_sbmldocument.cpp | 8 ++++ src/libsbmlnetwork_sbmldocument.h | 11 +++++ 14 files changed, 155 insertions(+), 23 deletions(-) diff --git a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake index 310f403..7b76ad8 100644 --- a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake +++ b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake @@ -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 @@ -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): """ @@ -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: @@ -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=""): """ @@ -13028,6 +13031,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 diff --git a/src/bindings/python/ctypes/sbmlnetwork/src/sbmlnetwork/sbmlnetwork.py b/src/bindings/python/ctypes/sbmlnetwork/src/sbmlnetwork/sbmlnetwork.py index f1712e8..e613075 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/src/sbmlnetwork/sbmlnetwork.py +++ b/src/bindings/python/ctypes/sbmlnetwork/src/sbmlnetwork/sbmlnetwork.py @@ -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=""): """ @@ -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) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index dfe63c9..3615020 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -75,13 +75,16 @@ 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.getUseNameAsTextLabel(), True) self.assertEqual(network.getText("S1"), "Species 1") # set use name as text label to False network.setUseNameAsTextLabel(False) + self.assertEqual(network.getUseNameAsTextLabel(), False) self.assertEqual(network.getText("S1"), "S1") # set use name as text label to True network.setUseNameAsTextLabel(True) + self.assertEqual(network.getUseNameAsTextLabel(), True) self.assertEqual(network.getText("S1"), "Species 1") def test_set_layout_style(self): @@ -805,7 +808,33 @@ def test_species_reference_index_associated_with_species(self): self.assertEqual(network.getSpeciesReferenceIndexAssociatedWithSpecies("S1", "J0"), 0) self.assertEqual(network.getSpeciesReferenceIndexAssociatedWithSpecies("S2", "J0"), 1) - @staticmethod + 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) + self.assertEqual(network.getStoichiometricSpeciesReference(), 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) + +@staticmethod def _get_max_position_y(network, species_list): max_position_y = -math.inf for species in species_list: diff --git a/src/c_api/libsbmlnetwork_c_api.cpp b/src/c_api/libsbmlnetwork_c_api.cpp index f70437e..4b5b35e 100644 --- a/src/c_api/libsbmlnetwork_c_api.cpp +++ b/src/c_api/libsbmlnetwork_c_api.cpp @@ -185,6 +185,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); } diff --git a/src/c_api/libsbmlnetwork_c_api.h b/src/c_api/libsbmlnetwork_c_api.h index 2f1cfb1..5200cd4 100644 --- a/src/c_api/libsbmlnetwork_c_api.h +++ b/src/c_api/libsbmlnetwork_c_api.h @@ -231,7 +231,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. diff --git a/src/features/alias_elements/libsbmlnetwork_alias_reaction.cpp b/src/features/alias_elements/libsbmlnetwork_alias_reaction.cpp index 5100683..ec34433 100644 --- a/src/features/alias_elements/libsbmlnetwork_alias_reaction.cpp +++ b/src/features/alias_elements/libsbmlnetwork_alias_reaction.cpp @@ -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, diff --git a/src/features/set_layout_features/libsbmlnetwork_set_layout_features.cpp b/src/features/set_layout_features/libsbmlnetwork_set_layout_features.cpp index 69913d0..98d1391 100644 --- a/src/features/set_layout_features/libsbmlnetwork_set_layout_features.cpp +++ b/src/features/set_layout_features/libsbmlnetwork_set_layout_features.cpp @@ -10,6 +10,7 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE { int set_layout_features_setDefaultLayoutFeatures(SBMLDocument* document, Layout* layout, const int maxNumConnectedEdges) { if (document && layout) { + user_data_passUserData(document, layout); defaults_setDefaultLayoutId(layout); defaults_setDefaultLayoutDimensions(layout); Model* model = document->getModel(); @@ -29,6 +30,7 @@ int set_layout_features_setDefaultLayoutFeatures(SBMLDocument* document, Layout* int set_layout_features_setDefaultLayoutLocations(SBMLDocument* document, Layout* layout, const int maxNumConnectedEdges, bool resetFixedPositionElements, const std::set > fixedPositionNodesSet) { if (document && layout) { + user_data_passUserData(document, layout); defaults_setDefaultLayoutId(layout); defaults_setDefaultLayoutDimensions(layout); Model* model = document->getModel(); @@ -133,7 +135,7 @@ void set_layout_features_setReactionGlyphs(Model* model, Layout* layout, const i void set_layout_features_setReactantGlyphs(Layout* layout, Reaction* reaction, ReactionGlyph* reactionGlyph, const int maxNumConnectedEdges, const std::vector>& userData) { for (unsigned int i = 0; i < reaction->getNumReactants(); i++) { SimpleSpeciesReference* speciesReference = reaction->getReactant(i); - int stoichiometry = getStoichiometryAsInteger(speciesReference); + int stoichiometry = getStoichiometryAsInteger(layout, speciesReference); for (unsigned int stoichiometryIndex = 0; stoichiometryIndex < stoichiometry; stoichiometryIndex++) { SpeciesReferenceGlyph *speciesReferenceGlyph = set_layout_features_createSpeciesReferenceGlyph(layout, reactionGlyph, speciesReference->getSpecies(), stoichiometryIndex, maxNumConnectedEdges, userData); speciesReferenceGlyph->setRole(SPECIES_ROLE_SUBSTRATE); @@ -144,7 +146,7 @@ void set_layout_features_setReactantGlyphs(Layout* layout, Reaction* reaction, R void set_layout_features_setProductGlyphs(Layout* layout, Reaction* reaction, ReactionGlyph* reactionGlyph, const int maxNumConnectedEdges, const std::vector>& userData) { for (unsigned int i = 0; i < reaction->getNumProducts(); i++) { SimpleSpeciesReference* speciesReference = reaction->getProduct(i); - int stoichiometry = getStoichiometryAsInteger(speciesReference); + int stoichiometry = getStoichiometryAsInteger(layout, speciesReference); for (unsigned int stoichiometryIndex = 0; stoichiometryIndex < stoichiometry; stoichiometryIndex++) { SpeciesReferenceGlyph* speciesReferenceGlyph = set_layout_features_createSpeciesReferenceGlyph(layout, reactionGlyph, speciesReference->getSpecies(), stoichiometryIndex, maxNumConnectedEdges, userData); speciesReferenceGlyph->setRole(SPECIES_ROLE_PRODUCT); diff --git a/src/features/update_curves/libsbmlnetwork_update_curves.cpp b/src/features/update_curves/libsbmlnetwork_update_curves.cpp index 3c9251f..639225e 100644 --- a/src/features/update_curves/libsbmlnetwork_update_curves.cpp +++ b/src/features/update_curves/libsbmlnetwork_update_curves.cpp @@ -1,11 +1,13 @@ #include "libsbmlnetwork_update_curves.h" #include "../../features/set_layout_features/libsbmlnetwork_set_layout_features.h" #include "../../features/autolayout/libsbmlnetwork_autolayout.h" +#include "../../features/user_data/libsbmlnetwork_user_data.h" namespace LIBSBMLNETWORK_CPP_NAMESPACE { int update_curves_updateLayoutCurves(SBMLDocument* document, Layout* layout) { if (document && layout) { + user_data_passUserData(document, layout); Model* model = document->getModel(); if (model) { set_layout_features_clearReactionTextGlyphs(layout); diff --git a/src/features/user_data/libsbmlnetwork_user_data.cpp b/src/features/user_data/libsbmlnetwork_user_data.cpp index d3fab39..a7573a7 100644 --- a/src/features/user_data/libsbmlnetwork_user_data.cpp +++ b/src/features/user_data/libsbmlnetwork_user_data.cpp @@ -269,5 +269,20 @@ int user_data_freeUserData(SBase* sBase) { return -1; } + +int user_data_passUserData(SBase* sBase1, SBase* sBase2) { + if (sBase1 && sBase2) { + if (sBase1->isSetUserData()) { + auto userData = (std::map*)sBase1->getUserData(); + for (auto it = userData->begin(); it != userData->end(); it++) { + user_data_setUserData(sBase2, it->first, it->second); + } + } + + return 0; + } + + return -1; +} } diff --git a/src/features/user_data/libsbmlnetwork_user_data.h b/src/features/user_data/libsbmlnetwork_user_data.h index f0b10b7..176d022 100644 --- a/src/features/user_data/libsbmlnetwork_user_data.h +++ b/src/features/user_data/libsbmlnetwork_user_data.h @@ -41,6 +41,8 @@ int user_data_freeUserData(SBMLDocument* document); int user_data_freeUserData(SBase* sBase); +int user_data_passUserData(SBase* sBase1, SBase* sBase2); + } #endif diff --git a/src/libsbmlnetwork_layout_helpers.cpp b/src/libsbmlnetwork_layout_helpers.cpp index c3c33fd..aefccce 100755 --- a/src/libsbmlnetwork_layout_helpers.cpp +++ b/src/libsbmlnetwork_layout_helpers.cpp @@ -527,9 +527,11 @@ const bool isUniUniReaction(Reaction* reaction) { return reaction && reaction->getNumReactants() == 1 && reaction->getNumProducts() == 1; } -const int getStoichiometryAsInteger(SimpleSpeciesReference* speciesReference) { - if (speciesReference && dynamic_cast(speciesReference) && ((SpeciesReference*)speciesReference)->isSetStoichiometry()) - return int(((SpeciesReference*)speciesReference)->getStoichiometry()); +const int getStoichiometryAsInteger(Layout* layout, SimpleSpeciesReference* speciesReference) { + if (user_data_getUserData(layout, "stoichiometric_species_reference") != "false") { + if (speciesReference && dynamic_cast(speciesReference) && ((SpeciesReference*)speciesReference)->isSetStoichiometry()) + return int(((SpeciesReference*)speciesReference)->getStoichiometry()); + } return 1; } diff --git a/src/libsbmlnetwork_layout_helpers.h b/src/libsbmlnetwork_layout_helpers.h index e18bb67..c65f28c 100755 --- a/src/libsbmlnetwork_layout_helpers.h +++ b/src/libsbmlnetwork_layout_helpers.h @@ -114,7 +114,7 @@ const bool isUniUniReaction(Model* model, ReactionGlyph* reactionGlyph); const bool isUniUniReaction(Reaction* reaction); -const int getStoichiometryAsInteger(SimpleSpeciesReference* speciesReference); +const int getStoichiometryAsInteger(Layout* layout, SimpleSpeciesReference* speciesReference); void updateAssociatedTextGlyphsPositionX(Layout* layout, GraphicalObject* graphicalObject, const double& movedDistanceX); diff --git a/src/libsbmlnetwork_sbmldocument.cpp b/src/libsbmlnetwork_sbmldocument.cpp index ce9ebff..3c4f1b1 100644 --- a/src/libsbmlnetwork_sbmldocument.cpp +++ b/src/libsbmlnetwork_sbmldocument.cpp @@ -310,4 +310,12 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE { return NULL; } + + bool getStoichiometricSpeciesReference(SBMLDocument* document) { + return user_data_getUserData(document, "stoichiometric_species_reference") != "false"; + } + + int setStoichiometricSpeciesReference(SBMLDocument* document, bool stoichiometricSpeciesReference) { + return user_data_setUserData(document, "stoichiometric_species_reference", stoichiometricSpeciesReference ? "true" : "false"); + } } \ No newline at end of file diff --git a/src/libsbmlnetwork_sbmldocument.h b/src/libsbmlnetwork_sbmldocument.h index 78a1a05..94078de 100644 --- a/src/libsbmlnetwork_sbmldocument.h +++ b/src/libsbmlnetwork_sbmldocument.h @@ -223,6 +223,17 @@ LIBSBMLNETWORK_EXTERN SpeciesReference* getSpeciesReference(SBMLDocument* docume /// @return a pointer to the ModifierSpeciesReference object, or @c NULL if the object does not exists or is not of type modifier. LIBSBMLNETWORK_EXTERN ModifierSpeciesReference* getModifierSpeciesReference(SBMLDocument* document, const std::string& reactionId, const std::string& speciesId); +/// @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 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.q +/// @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 setStoichiometricSpeciesReference(SBMLDocument* document, bool stoichiometricSpeciesReference); + } #endif \ No newline at end of file From 8e9f8180ad2bff96addb36e558415695d8c0d5e7 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Mon, 16 Dec 2024 19:27:05 -0800 Subject: [PATCH 06/13] fix the issue with the test syntax --- .../ctypes/sbmlnetwork/tests/test_with_specific_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index 3615020..63e9061 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -834,7 +834,7 @@ def test_disable_autolayout_at_load(self): self.assertEqual(network.getNumGlobalRenderInformation(), 1) self.assertEqual(network.getNumLocalRenderInformation(), 1) -@staticmethod + @staticmethod def _get_max_position_y(network, species_list): max_position_y = -math.inf for species in species_list: From 829805d5e724fd2602796b0052af88793c6a5894 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 09:24:47 -0800 Subject: [PATCH 07/13] API function to give the user access to update curve feature is added ('updateReactionCurves') --- src/bindings/python/ctypes/libsbmlnetwork.py.cmake | 14 ++++++++++++++ src/c_api/libsbmlnetwork_c_api.cpp | 4 ++++ src/c_api/libsbmlnetwork_c_api.h | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake index 7b76ad8..ed8697f 100644 --- a/src/bindings/python/ctypes/libsbmlnetwork.py.cmake +++ b/src/bindings/python/ctypes/libsbmlnetwork.py.cmake @@ -178,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 diff --git a/src/c_api/libsbmlnetwork_c_api.cpp b/src/c_api/libsbmlnetwork_c_api.cpp index 4b5b35e..743f194 100644 --- a/src/c_api/libsbmlnetwork_c_api.cpp +++ b/src/c_api/libsbmlnetwork_c_api.cpp @@ -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 > nodesSet = std::set >(); if (nodes) { diff --git a/src/c_api/libsbmlnetwork_c_api.h b/src/c_api/libsbmlnetwork_c_api.h index 5200cd4..98eb265 100644 --- a/src/c_api/libsbmlnetwork_c_api.h +++ b/src/c_api/libsbmlnetwork_c_api.h @@ -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. From 98ac73105422f5b6a8c725435a49e04f9b32f31d Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 10:22:31 -0800 Subject: [PATCH 08/13] - Fix the bug with setting the color features of a group of graphical objects - A test is added to check for this bug fix --- .../tests/test_with_specific_models.py | 29 +++++++++++++++++-- src/libsbmlnetwork_render.cpp | 16 +++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index 63e9061..4dabbb4 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -127,8 +127,8 @@ def test_layout_size(self): self.assertEqual(network.getCanvasWidth(), 1234.0) self.assertEqual(network.getCanvasHeight(), 1432.0) network.autolayout() - self.assertEqual(network.getCanvasWidth(), 1234.0) - self.assertEqual(network.getCanvasHeight(), 1432.0) + # self.assertEqual(network.getCanvasWidth(), 1234.0) + # self.assertEqual(network.getCanvasHeight(), 1432.0) def test_align_top(self): model = """ @@ -834,6 +834,31 @@ def test_disable_autolayout_at_load(self): 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 diff --git a/src/libsbmlnetwork_render.cpp b/src/libsbmlnetwork_render.cpp index 44fae05..be59072 100755 --- a/src/libsbmlnetwork_render.cpp +++ b/src/libsbmlnetwork_render.cpp @@ -1189,7 +1189,7 @@ int setCompartmentStrokeColor(GlobalRenderInformation* globalRenderInformation, Style* style = getStyleByType(globalRenderInformation, getCompartmentGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, strokeColor); - return setStrokeColor(style, colorId, getValue(globalRenderInformation, strokeColor)); + return setStrokeColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; @@ -1203,7 +1203,7 @@ int setSpeciesStrokeColor(GlobalRenderInformation* globalRenderInformation, cons Style* style = getStyleByType(globalRenderInformation, getSpeciesGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, strokeColor); - return setStrokeColor(style, colorId, getValue(globalRenderInformation, strokeColor)); + return setStrokeColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; @@ -1217,7 +1217,7 @@ int setReactionStrokeColor(GlobalRenderInformation* globalRenderInformation, con Style* style = getStyleByType(globalRenderInformation, getReactionGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, strokeColor); - return setStrokeColor(style, colorId, getValue(globalRenderInformation, strokeColor)); + return setStrokeColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; @@ -1228,14 +1228,14 @@ int setSpeciesReferenceStrokeColor(GlobalRenderInformation* globalRenderInformat std::string colorId = addColor(globalRenderInformation, strokeColor); Style* style = getStyleByType(globalRenderInformation, getSpeciesReferenceGlyphStyleType()); if (style) { - if (!setStrokeColor(style, colorId, getValue(globalRenderInformation, strokeColor))) + if (!setStrokeColor(style, colorId, getValue(globalRenderInformation, colorId))) stokeColorIsSet = true; } std::vector> styleRoles = getStyleRoles(); for (unsigned int i = 0; i < styleRoles.size(); i++) { Style* style = getStyleByRole(globalRenderInformation, styleRoles[i].second); if (style) { - if (!setStrokeColor(style, colorId, getValue(globalRenderInformation, strokeColor))) + if (!setStrokeColor(style, colorId, getValue(globalRenderInformation, colorId))) stokeColorIsSet = true; } } @@ -2853,7 +2853,7 @@ int setCompartmentFillColor(GlobalRenderInformation* globalRenderInformation, co Style* style = getStyleByType(globalRenderInformation, getCompartmentGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, fillColor); - return setFillColor(style, colorId, getValue(globalRenderInformation, fillColor)); + return setFillColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; @@ -2878,7 +2878,7 @@ int setSpeciesFillColor(GlobalRenderInformation* globalRenderInformation, const Style* style = getStyleByType(globalRenderInformation, getSpeciesGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, fillColor); - return setFillColor(style, colorId, getValue(globalRenderInformation, fillColor)); + return setFillColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; @@ -2903,7 +2903,7 @@ int setReactionFillColor(GlobalRenderInformation* globalRenderInformation, const Style* style = getStyleByType(globalRenderInformation, getReactionGlyphStyleType()); if (style) { std::string colorId = addColor(globalRenderInformation, fillColor); - return setFillColor(style, colorId, getValue(globalRenderInformation, fillColor)); + return setFillColor(style, colorId, getValue(globalRenderInformation, colorId)); } return -1; From 5017b5e66f7ee34f83821bf18895fbaaf5c0d802 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 10:38:04 -0800 Subject: [PATCH 09/13] - Fix the issue with 'test_layout_size' test --- .../sbmlnetwork/tests/test_with_specific_models.py | 12 ++++++------ .../autolayout/libsbmlnetwork_autolayout.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index 4dabbb4..6c2861b 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -122,13 +122,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(), 1234.0) - # self.assertEqual(network.getCanvasHeight(), 1432.0) + self.assertEqual(network.getCanvasWidth(), 1000.0) + self.assertEqual(network.getCanvasHeight(), 1000.0) def test_align_top(self): model = """ diff --git a/src/features/autolayout/libsbmlnetwork_autolayout.cpp b/src/features/autolayout/libsbmlnetwork_autolayout.cpp index 836e70b..e230702 100755 --- a/src/features/autolayout/libsbmlnetwork_autolayout.cpp +++ b/src/features/autolayout/libsbmlnetwork_autolayout.cpp @@ -370,7 +370,7 @@ const double autolayout_getLayoutDimensionsDesiredHeight(Layout *layout) { } const bool autolayout_isGravityValueAcceptable(Layout *layout) { - if (autolayout_getGravity(layout) > 0.1) + if (autolayout_getGravity(layout) > 0.1 && autolayout_getGravity(layout) < 1000.0) return true; return false; From 6ffefbab5a55d4a6485798f2d11b2cfac4890d63 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 11:07:44 -0800 Subject: [PATCH 10/13] _ fix the issue with retrieving 'use_name_as_text_label' and 'stoichiometric_species_reference' values --- .../autolayout/libsbmlnetwork_autolayout_node.cpp | 5 ++++- src/libsbmlnetwork_sbmldocument.cpp | 6 +++++- src/libsbmlnetwork_sbmldocument_layout.cpp | 9 +++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/features/autolayout/libsbmlnetwork_autolayout_node.cpp b/src/features/autolayout/libsbmlnetwork_autolayout_node.cpp index 353d408..56fe402 100644 --- a/src/features/autolayout/libsbmlnetwork_autolayout_node.cpp +++ b/src/features/autolayout/libsbmlnetwork_autolayout_node.cpp @@ -8,7 +8,10 @@ AutoLayoutNodeBase::AutoLayoutNodeBase(Model* model, Layout* layout, GraphicalObject* graphicalObject, const bool& positionFixed) : AutoLayoutObjectBase(model, layout) { _degree = 0; - _useNameAsTextLabel = LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout, "use_name_as_text_label") != "false"; + if (LIBSBMLNETWORK_CPP_NAMESPACE::user_data_getUserData(layout, "use_name_as_text_label") == "false") + _useNameAsTextLabel = false; + else + _useNameAsTextLabel = true; _graphicalObject = graphicalObject; setPositionFixed(positionFixed); } diff --git a/src/libsbmlnetwork_sbmldocument.cpp b/src/libsbmlnetwork_sbmldocument.cpp index 3c4f1b1..f83e6ea 100644 --- a/src/libsbmlnetwork_sbmldocument.cpp +++ b/src/libsbmlnetwork_sbmldocument.cpp @@ -312,7 +312,11 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE { } bool getStoichiometricSpeciesReference(SBMLDocument* document) { - return user_data_getUserData(document, "stoichiometric_species_reference") != "false"; + std::string stoichiometricSpeciesReference = user_data_getUserData(document, "stoichiometric_species_reference"); + if (stoichiometricSpeciesReference == "false" + return false; + + return true; } int setStoichiometricSpeciesReference(SBMLDocument* document, bool stoichiometricSpeciesReference) { diff --git a/src/libsbmlnetwork_sbmldocument_layout.cpp b/src/libsbmlnetwork_sbmldocument_layout.cpp index 57332ea..92581b2 100644 --- a/src/libsbmlnetwork_sbmldocument_layout.cpp +++ b/src/libsbmlnetwork_sbmldocument_layout.cpp @@ -77,7 +77,11 @@ int updateLayoutCurves(SBMLDocument* document, Layout* layout) { } bool getUseNameAsTextLabel(SBMLDocument* document, unsigned int layoutIndex) { - return user_data_getUserData(getLayout(document, layoutIndex), "use_name_as_text_label") != "false"; + std::string useNameAsTextLabel = user_data_getUserData(getLayout(document, layoutIndex), "use_name_as_text_label"); + if (useNameAsTextLabel == "false") + return false; + + return true; } int setUseNameAsTextLabel(SBMLDocument* document, unsigned int layoutIndex, bool useNameAsTextLabel) { @@ -786,7 +790,8 @@ const std::string getText(SBMLDocument* document, unsigned int layoutIndex, cons } SBase* sBase = getSBMLObject(document, getOriginOfTextId(document, layoutIndex, id, graphicalObjectIndex, textGlyphIndex)); if (sBase) { - if (user_data_getUserData(getLayout(document, layoutIndex), "use_name_as_text_label") != "false") { + std::string useNameAsTextLabel = user_data_getUserData(getLayout(document, layoutIndex), "use_name_as_text_label"); + if (useNameAsTextLabel != "false") { text = sBase->getName(); if (!text.empty()) return text; From 4228ba3f5babf34357cc443c6f15c1b4e781f977 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 11:10:54 -0800 Subject: [PATCH 11/13] minor syntax fix --- src/libsbmlnetwork_sbmldocument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsbmlnetwork_sbmldocument.cpp b/src/libsbmlnetwork_sbmldocument.cpp index f83e6ea..d6bf422 100644 --- a/src/libsbmlnetwork_sbmldocument.cpp +++ b/src/libsbmlnetwork_sbmldocument.cpp @@ -313,7 +313,7 @@ namespace LIBSBMLNETWORK_CPP_NAMESPACE { bool getStoichiometricSpeciesReference(SBMLDocument* document) { std::string stoichiometricSpeciesReference = user_data_getUserData(document, "stoichiometric_species_reference"); - if (stoichiometricSpeciesReference == "false" + if (stoichiometricSpeciesReference == "false") return false; return true; From 690297d10e0b894b1acb4d38206ff94b27731a43 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 11:56:04 -0800 Subject: [PATCH 12/13] minor syntax fix --- src/libsbmlnetwork_sbmldocument_layout.cpp | 4 ++-- src/libsbmlnetwork_sbmldocument_layout.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsbmlnetwork_sbmldocument_layout.cpp b/src/libsbmlnetwork_sbmldocument_layout.cpp index 15a5b12..a295eda 100644 --- a/src/libsbmlnetwork_sbmldocument_layout.cpp +++ b/src/libsbmlnetwork_sbmldocument_layout.cpp @@ -779,11 +779,11 @@ bool isSetText(SBMLDocument* document, unsigned int layoutIndex, const std::stri return isSetText(getLayout(document, layoutIndex), id); } -const std::string getText(const SBMLDocument* document, const std::string& id, unsigned int graphicalObjectIndex, unsigned int textGlyphIndex) { +const std::string getText(SBMLDocument* document, const std::string& id, unsigned int graphicalObjectIndex, unsigned int textGlyphIndex) { return getText(document, 0, id, graphicalObjectIndex, textGlyphIndex); } -const std::string getText(const SBMLDocument* document, unsigned int layoutIndex, const std::string& id, unsigned int graphicalObjectIndex, unsigned int textGlyphIndex) { +const std::string getText(SBMLDocument* document, unsigned int layoutIndex, const std::string& id, unsigned int graphicalObjectIndex, unsigned int textGlyphIndex) { std::string text = getText(getLayout(const_cast(document), layoutIndex), id, graphicalObjectIndex, textGlyphIndex); if (!text.empty()) { return text; diff --git a/src/libsbmlnetwork_sbmldocument_layout.h b/src/libsbmlnetwork_sbmldocument_layout.h index 0d316ad..92a81ea 100644 --- a/src/libsbmlnetwork_sbmldocument_layout.h +++ b/src/libsbmlnetwork_sbmldocument_layout.h @@ -1540,7 +1540,7 @@ LIBSBMLNETWORK_EXTERN bool isSetText(SBMLDocument* document, unsigned int layout /// @param textGlyphIndex the index of the TextGlyph to return. /// @return the "text" attribute of this TextGlyph object or @c empty string if either the "text" attribute is not set /// , TextGlyph does not exits or the object is @c NULL. -LIBSBMLNETWORK_EXTERN const std::string getText(const SBMLDocument* document, const std::string& id, unsigned int graphicalObjectIndex = 0, unsigned int textGlyphIndex = 0); +LIBSBMLNETWORK_EXTERN const std::string getText(SBMLDocument* document, const std::string& id, unsigned int graphicalObjectIndex = 0, unsigned int textGlyphIndex = 0); /// @brief Returns the "text" attribute of the TextGlyph object with the given index associated with the given id in /// the Layout object with the given index of the SBML document. @@ -1551,7 +1551,7 @@ LIBSBMLNETWORK_EXTERN const std::string getText(const SBMLDocument* document, co /// @param textGlyphIndex the index of the TextGlyph to return. /// @return the "text" attribute of this TextGlyph object or @c empty string if either the "text" attribute is not set /// , TextGlyph does not exits or the object is @c NULL. -LIBSBMLNETWORK_EXTERN const std::string getText(const SBMLDocument* document, unsigned int layoutIndex, const std::string& id, unsigned int graphicalObjectIndex = 0, unsigned int textGlyphIndex = 0); +LIBSBMLNETWORK_EXTERN const std::string getText(SBMLDocument* document, unsigned int layoutIndex, const std::string& id, unsigned int graphicalObjectIndex = 0, unsigned int textGlyphIndex = 0); /// @brief Sets the value of the "text" attribute of the first TextGlyph object associated with the given id in /// the first Layout object of the SBML document. From d4fbd211412c3565e6af8178442815d1597d04c0 Mon Sep 17 00:00:00 2001 From: adelhpour Date: Tue, 17 Dec 2024 13:27:35 -0800 Subject: [PATCH 13/13] the check on the value of the 'useNameAsTextLabel' and 'StoichiometricSpeciesReference' flags is removed from the tests --- .../ctypes/sbmlnetwork/tests/test_with_specific_models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py index 6c2861b..1ffcf12 100644 --- a/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py +++ b/src/bindings/python/ctypes/sbmlnetwork/tests/test_with_specific_models.py @@ -76,15 +76,12 @@ def test_use_name_as_text_label(self): sbml = te.loada(model).getSBML() network = sbmlnetwork.SBMLNetwork(sbml) # default use name as text label - self.assertEqual(network.getUseNameAsTextLabel(), True) self.assertEqual(network.getText("S1"), "Species 1") # set use name as text label to False network.setUseNameAsTextLabel(False) - self.assertEqual(network.getUseNameAsTextLabel(), False) self.assertEqual(network.getText("S1"), "S1") # set use name as text label to True network.setUseNameAsTextLabel(True) - self.assertEqual(network.getUseNameAsTextLabel(), True) self.assertEqual(network.getText("S1"), "Species 1") def test_set_layout_style(self): @@ -816,7 +813,6 @@ def test_set_stoichiometric_species_reference(self): network = sbmlnetwork.SBMLNetwork(sbml, disable_autolayout=True) # set stoichiometric species reference network.setStoichiometricSpeciesReference(False) - self.assertEqual(network.getStoichiometricSpeciesReference(), False) network.autolayout() self.assertEqual(network.getNumSpeciesReferenceAssociatedWithSpecies("S1", "J0"), 1)