From b6eed1fd2fcdf9c658e91a4a6156749f9282b47e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6nig?= Date: Sat, 26 Oct 2024 19:21:01 +0200 Subject: [PATCH] working on visualization --- setup.cfg | 34 ++++++++-------- src/sbmlutils/cytoscape.py | 82 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/setup.cfg b/setup.cfg index 6262e9a8..705dda65 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ parse = (?P\d+) \.(?P\d+) \.(?P\d+) (?P[a]*)(?P\d*) -serialize = +serialize = {major}.{minor}.{patch}{release}{num} {major}.{minor}.{patch} tag_name = {new_version} @@ -15,7 +15,7 @@ tag_name = {new_version} name = sbmlutils url = https://github.com/matthiaskoenig/sbmlutils download_url = https://pypi.org/project/sbmlutils -project_urls = +project_urls = Source Code = https://github.com/matthiaskoenig/sbmlutils Documentation = https://sbmlutils.readthedocs.io Bug Tracker = https://github.com/matthiaskoenig/sbmlutils/issues @@ -23,7 +23,7 @@ author = Matthias Koenig author_email = konigmatt@googlemail.com maintainer = Matthias Koenig maintainer_email = konigmatt@googlemail.com -classifiers = +classifiers = Development Status :: 5 - Production/Stable Intended Audience :: Science/Research License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) @@ -38,7 +38,7 @@ license = LGPL-3.0 description = sbmlutils are utilities for working with SBML. long_description = file: README.rst long_description_content_type = text/x-rst -keywords = +keywords = modeling standardization SBML @@ -46,9 +46,9 @@ keywords = [options] zip_safe = True python_requires = >=3.10 -install_requires = +install_requires = pymetadata>=0.4.1 - + depinfo rich lxml @@ -56,7 +56,7 @@ install_requires = jinja2 xmltodict pydantic>2.8 - + setuptools # fix for colorbrewer dependency of py4cytoscape numpy>=1.26.4 python-libsbml>=5.20.4 @@ -65,24 +65,24 @@ install_requires = pandas>=2.2.0 tabulate>=0.9.0 pint>=0.24.3 - + markdown-it-py>=3.0.0 openpyxl>=3.1.5 xmlschema>=3.3.2 matplotlib>=3.9 - py4cytoscape>=1.9.0 - libroadrunner>=1.27.0 - + py4cytoscape>=1.11.0 + libroadrunner>=2.7.0 + uvicorn>=0.30.6 fastapi>=0.112.0 python-multipart>=0.0.9 -tests_require = +tests_require = tox>=3.24.3 pytest>=7.0.1 -setup_requires = +setup_requires = pytest-runner packages = find: -package_dir = +package_dir = = src include_package_data = True @@ -93,7 +93,7 @@ test = pytest where = src [options.extras_require] -development = +development = pip-tools>=7.4.1 black>=24.8.0 bump2version>=1.0.1 @@ -105,7 +105,7 @@ development = pytest>=7.4.0 pytest-cov>=4.1.0 beautifulsoup4>=4.12.3 -docs = +docs = sphinx>=3.4.3 ipykernel>=5.4.3 nbsphinx>=0.8.1 @@ -119,7 +119,7 @@ universal = 1 [bumpversion:part:release] optional_value = placeholder first_value = placeholder -values = +values = placeholder a diff --git a/src/sbmlutils/cytoscape.py b/src/sbmlutils/cytoscape.py index b026ae3f..0cefd865 100644 --- a/src/sbmlutils/cytoscape.py +++ b/src/sbmlutils/cytoscape.py @@ -3,12 +3,14 @@ import os import tempfile +import pandas as pd os.environ["PY4CYTOSCAPE_DETAIL_LOGGER_DIR"] = str(tempfile.gettempdir()) from pathlib import Path # noqa: E402 -from typing import Any, Union # noqa: E402 +from typing import Any, Union, Optional # noqa: E402 +import libsbml import py4cytoscape as p4c # type: ignore # noqa: E402 from requests.exceptions import RequestException # noqa: E402 @@ -30,8 +32,13 @@ def visualize_antimony(source: Union[Path, str], delete_session: bool = False) - visualize_sbml(Path(f_tmp.name), delete_session=delete_session) -def visualize_sbml(sbml_path: Path, delete_session: bool = False) -> None: - """Visualize SBML networks in cytoscape.""" +def visualize_sbml(sbml_path: Path, delete_session: bool = False) -> Optional[int]: + """Visualize SBML networks in cytoscape. + + Returns dictionary with "networks" and "views". + """ + if sbml_path.suffix != ".xml": + console.error(f"SBML path {sbml_path} does not have .xml extension") try: console.print(p4c.cytoscape_version_info()) @@ -39,10 +46,77 @@ def visualize_sbml(sbml_path: Path, delete_session: bool = False) -> None: if delete_session: p4c.session.close_session(save_before_closing=False) - p4c.networks.import_network_from_file(str(sbml_path)) + networks_views = p4c.networks.import_network_from_file(str(sbml_path)) + console.print(f"{networks_views}") + network = networks_views["networks"][1] + p4c.set_current_view(network=network) # set the base network + return network + + return networks_views except RequestException: logger.error( "Could not connect to a running Cytoscape instance. " "Start Cytoscape before running the python script." ) + return None + + + + + + + +def read_layout_xml(sbml_path: Path, xml_path: Path) -> pd.DataFrame: + """Read own xml layout information form cytoscape.""" + # read positions + df: pd.DataFrame = pd.read_xml(xml_path, xpath="//boundingBox") + df = df[['id', 'xpos', 'ypos']] + df.rename(columns={"xpos": "x", "ypos": "y"}, inplace=True) + df.set_index("id", inplace=True) + return df + +def apply_layout(network, layout: pd.DataFrame) -> None: + """Apply layout information from Cytoscape to SBML networks.""" + + # get SUIDs, sbml_id from node table; + df_nodes = p4c.get_table_columns(table="node", columns=["sbml id"], network=network) + console.print(df_nodes) + sid2suid = {row["sbml id"]: suid for suid, row in df_nodes.iterrows()} + console.print(sid2suid) + + # FIXME: necessary to check that all sids exist + suids = [sid2suid[sid] for sid in layout.index.values] + x_values = layout["x"].values.tolist() + y_values = layout["y"].values.tolist() + + # set positions + # see: https://github.com/cytoscape/py4cytoscape/issues/144 + p4c.set_node_position_bypass(suids, new_x_locations=x_values, new_y_locations=y_values, network=network) + # p4c.set_node_property_bypass(suids, new_values=x_values, visual_property='NODE_X_LOCATION', network=network) + # p4c.set_node_property_bypass(suids, new_values=y_values, visual_property='NODE_Y_LOCATION', network=network) + p4c.set_current_view(network=network) + + # remove bypass + # p4c.clear_node_property_bypass(suids, visual_property='NODE_X_LOCATION', network=network) + # p4c.clear_node_property_bypass(suids, visual_property='NODE_Y_LOCATION', network=network) + + # fit content + p4c.fit_content() + + + +if __name__ == "__main__": + pass + # # visual style + # p4c.set_visual_style('Marquee') + # + # # fit the content + # p4c.fit_content() + + # p4c.load_table_data + + # annotations! + + # network_views.export_image +