verify Cyto API conn, add docs

This commit is contained in:
Florian Förster
2024-07-19 10:31:17 +02:00
parent d2165afbfd
commit 578c543a3e
6 changed files with 255 additions and 398 deletions

View File

@@ -10,6 +10,7 @@ LOGGING_LEVEL_GRAPHS: Final[LoggingLevels] = LoggingLevels.INFO
LOGGING_LEVEL_TIMELINE: Final[LoggingLevels] = LoggingLevels.DEBUG
LOGGING_LEVEL_TOKEN_ANALYSIS: Final[LoggingLevels] = LoggingLevels.INFO
LOGGING_LEVEL_SHARED_HELPERS: Final[LoggingLevels] = LoggingLevels.INFO
LOGGING_LEVEL_RENDERING: Final[LoggingLevels] = LoggingLevels.INFO
logger_shared_helpers = logging.getLogger('lang_main.shared')
logger_shared_helpers.setLevel(LOGGING_LEVEL_SHARED_HELPERS)
@@ -23,3 +24,5 @@ logger_token_analysis.setLevel(LOGGING_LEVEL_TOKEN_ANALYSIS)
logger_preprocess.setLevel(LOGGING_LEVEL_PREPROCESS)
logger_pipelines = logging.getLogger('lang_main.pipelines')
logger_pipelines.setLevel(LOGGING_LEVEL_PIPELINES)
logger_rendering = logging.getLogger('lang_main.render')
logger_rendering.setLevel(LOGGING_LEVEL_RENDERING)

View File

@@ -295,14 +295,15 @@ class Pipeline(BasePipeline):
else:
args = ret
if args is not None and action_kwargs:
if args is not None:
ret = action(*args, **action_kwargs)
elif args is not None:
ret = action(*args)
elif args is None and action_kwargs:
ret = action(**action_kwargs)
# elif args is not None:
# ret = action(*args)
# elif args is None and action_kwargs:
# ret = action(**action_kwargs)
else:
ret = action()
# ret = action()
ret = action(**action_kwargs)
if ret is not None and not isinstance(ret, tuple):
ret = (ret,)

View File

@@ -182,6 +182,7 @@ def build_tk_graph_rescaling_pipe() -> Pipeline:
return pipe_graph_rescaling
# ** token analysis: rendering
def build_tk_graph_rendering_pipe() -> Pipeline:
pipe_graph_rendering = Pipeline(
name='Graph_Static-Rendering',

View File

@@ -5,6 +5,8 @@ from typing import cast
import py4cytoscape as p4c
from networkx import DiGraph, Graph
from py4cytoscape.exceptions import CyError
from requests.exceptions import RequestException
from lang_main.constants import (
CYTO_BASE_NETWORK_NAME,
@@ -19,6 +21,7 @@ from lang_main.constants import (
PROPERTY_NAME_DEGREE_WEIGHTED,
SAVE_PATH_FOLDER,
)
from lang_main.loggers import logger_rendering as logger
from lang_main.types import (
CytoExportFileTypes,
CytoExportPageSizes,
@@ -29,9 +32,40 @@ from lang_main.types import (
# ** Cytoscape API related, using py4cytoscape
def verify_connection():
"""Cytoscape: checks if CyREST and Cytoscape versions are compatible nad
if Cytoscape API endpoint is reachable
Raises
------
CyError
incompatible CyREST or Cytoscape versions
RequestException
API endpoint not reachable
"""
try:
p4c.cytoscape_ping()
except CyError as error:
logger.error('[CyError] CyREST or Cytoscape version not supported.')
raise error
except RequestException as error:
logger.error('[CytoAPIConnection] Connection to CyREST API failed.')
raise error
def import_to_cytoscape(
graph: DiGraph | Graph,
) -> None:
"""Cytoscape: import NetworkX graph as new network collection
Parameters
----------
graph : DiGraph | Graph
NetworkX graph object
"""
logger.debug('Checking Cytoscape connection...')
verify_connection()
logger.debug('Importing network to Cytoscape...')
p4c.delete_all_networks()
p4c.create_network_from_networkx(
graph,
@@ -39,9 +73,11 @@ def import_to_cytoscape(
collection=CYTO_COLLECTION_NAME,
)
p4c.analyze_network(directed=False)
logger.debug('Importing network to Cytoscape successful.')
def reset_current_network_to_base() -> None:
"""resets to currently selected network in Cytoscape back to the base one"""
p4c.set_current_network(CYTO_BASE_NETWORK_NAME)
@@ -51,7 +87,21 @@ def export_network_to_image(
network_name: str = CYTO_BASE_NETWORK_NAME,
pdf_export_page_size: CytoExportPageSizes = 'A4',
) -> None:
# target_folder = Path.cwd() / 'results'
"""Cytoscape: export current selected view as image
Parameters
----------
filename : str
export filename
filetype : CytoExportFileTypes, optional
export filetype supported by Cytoscape, by default 'SVG'
network_name : str, optional
network to export, by default CYTO_BASE_NETWORK_NAME
pdf_export_page_size : CytoExportPageSizes, optional
page size which should be used for PDF exports supported by Cytoscape,
by default 'A4'
"""
logger.debug('Exporting image to file...')
target_folder = SAVE_PATH_FOLDER
if not target_folder.exists():
target_folder.mkdir(parents=True)
@@ -70,6 +120,7 @@ def export_network_to_image(
export_text_as_font=text_as_font,
page_size=pdf_export_page_size,
)
logger.debug('Exporting image to file successful.')
def layout_network(
@@ -77,15 +128,52 @@ def layout_network(
layout_properties: CytoLayoutProperties = CYTO_LAYOUT_PROPERTIES,
network_name: str = CYTO_BASE_NETWORK_NAME,
) -> None:
"""Cytoscape: apply a supported layout algorithm to currently selected
network
Parameters
----------
layout_name : CytoLayouts, optional
layout algorithm supported by Cytoscape (name of the CyREST API, does not
necessarily match the name in the Cytoscape UI),
by default CYTO_LAYOUT_NAME
layout_properties : CytoLayoutProperties, optional
configuration of parameters for the given layout algorithm, by default CYTO_LAYOUT_PROPERTIES
network_name : str, optional
network to apply the layout algorithm on, by default CYTO_BASE_NETWORK_NAME
"""
logger.debug('Applying layout to network...')
p4c.set_layout_properties(layout_name, layout_properties)
p4c.layout_network(layout_name=layout_name, network=network_name)
p4c.fit_content(selected_only=False, network=network_name)
logger.debug('Layout application to network successful.')
def apply_style_to_network(
style_name: str = CYTO_STYLESHEET_NAME,
pth_to_stylesheet: Path = CYTO_PATH_STYLESHEET,
network_name: str = CYTO_BASE_NETWORK_NAME,
) -> None:
"""Cytoscape: apply a chosen Cytoscape style to the defined network
Parameters
----------
style_name : str, optional
Cytoscape name of the style which should be applied,
by default CYTO_STYLESHEET_NAME
pth_to_stylesheet : Path, optional
path where the stylesheet definition in Cytoscape's XML format can
be found,
by default CYTO_PATH_STYLESHEET
network_name : str, optional
network to apply the style on, by default CYTO_BASE_NETWORK_NAME
Raises
------
FileNotFoundError
if provided stylesheet can not be found under the provided path
"""
logger.debug('Applying style to network...')
styles_avail = cast(list[str], p4c.get_visual_style_names())
if CYTO_STYLESHEET_NAME not in styles_avail:
if not pth_to_stylesheet.exists():
@@ -96,15 +184,36 @@ def apply_style_to_network(
)
p4c.import_visual_styles(str(pth_to_stylesheet))
p4c.set_visual_style(CYTO_STYLESHEET_NAME, network=network_name)
p4c.set_visual_style(style_name, network=network_name)
time.sleep(1) # if not waited image export could be without applied style
p4c.fit_content(selected_only=False, network=network_name)
logger.debug('Style application to network successful.')
def get_subgraph_node_selection(
network_name: str = CYTO_BASE_NETWORK_NAME,
property_degree_weighted: str = PROPERTY_NAME_DEGREE_WEIGHTED,
num_subgraphs: int = CYTO_NUMBER_SUBGRAPHS,
) -> list[CytoNodeID]:
"""Cytoscape: obtain the relevant nodes for iterative subgraph generation
Parameters
----------
network_name : str, optional
network to retrieve the nodes from, by default CYTO_BASE_NETWORK_NAME
property_degree_weighted : str, optional
property name which contains the weighted degree,
by default PROPERTY_NAME_DEGREE_WEIGHTED
num_subgraphs : int, optional
number of relevant nodes which form the basis to generate subgraphs from,
by default CYTO_NUMBER_SUBGRAPHS
Returns
-------
list[CytoNodeID]
list containing all relevant Cytoscape nodes
"""
logger.debug('Selecting nodes for subgraph generation...')
node_table = p4c.get_table_columns(network=network_name)
node_table['stress_norm'] = node_table['Stress'] / node_table['Stress'].max()
node_table[CYTO_SELECTION_PROPERTY] = (
@@ -113,22 +222,42 @@ def get_subgraph_node_selection(
* node_table['stress_norm']
)
node_table = node_table.sort_values(by=CYTO_SELECTION_PROPERTY, ascending=False)
node_table_choice = node_table.iloc[:CYTO_NUMBER_SUBGRAPHS, :]
node_table_choice = node_table.iloc[:num_subgraphs, :]
logger.debug('Selection of nodes for subgraph generation successful.')
return node_table_choice['SUID'].to_list()
def select_neighbours_of_node(
node: CytoNodeID,
neighbour_iter_depth: int = CYTO_ITER_NEIGHBOUR_DEPTH,
network_name: str = CYTO_BASE_NETWORK_NAME,
) -> None:
"""Cytoscape: iterative selection of a node's neighbouring nodes and
their connecting edges
Parameters
----------
node : CytoNodeID
node which neighbours should be selected
neighbour_iter_depth : int, optional
indicates how many levels of neighbours should be choosen, e.g. 1 --> only
first-level neighbours are considered which are directly connected to the node,
2 --> all nodes with iteration depth of 1 are chosen and additionally their
direct neighbours,
by default CYTO_ITER_NEIGHBOUR_DEPTH
network_name : str, optional
network to perform action on, by default CYTO_BASE_NETWORK_NAME
"""
logger.debug('Selecting node neighbours for %s...', node)
p4c.clear_selection(network=network_name)
p4c.select_nodes(node, network=network_name)
for _ in range(CYTO_ITER_NEIGHBOUR_DEPTH):
for _ in range(neighbour_iter_depth):
_ = p4c.select_first_neighbors(network=network_name)
_ = p4c.select_edges_connecting_selected_nodes()
logger.debug('Selection of node neighbours for %s successful.', node)
def make_subnetwork(
@@ -136,6 +265,19 @@ def make_subnetwork(
network_name: str = CYTO_BASE_NETWORK_NAME,
export_image: bool = True,
) -> None:
"""Cytoscape: generate a new subnetwork based on the currently
selected nodes and edges
Parameters
----------
index : int
id-like property to identify the subnetwork relative to its parent
network_name : str, optional
network to generate subnetwork from, by default CYTO_BASE_NETWORK_NAME
export_image : bool, optional
trigger image export of newly generated subnetwork, by default True
"""
logger.debug('Generating subnetwork with index %d...', index)
subnetwork_name = network_name + f'_sub_{index+1}'
p4c.create_subnetwork(
nodes='selected',
@@ -146,14 +288,33 @@ def make_subnetwork(
p4c.set_current_network(subnetwork_name)
p4c.fit_content(selected_only=False, network=subnetwork_name)
if export_image:
time.sleep(1)
export_network_to_image(filename=subnetwork_name, network_name=subnetwork_name)
logger.debug('Generation of subnetwork with index %d successful.', index)
def build_subnetworks(
nodes_to_analyse: Iterable[CytoNodeID],
network_name: str = CYTO_BASE_NETWORK_NAME,
export_image: bool = True,
) -> None:
"""Cytoscape: iteratively build subnetworks from a collection of nodes
and their respective neighbouring nodes
Parameters
----------
nodes_to_analyse : Iterable[CytoNodeID]
collection of nodes to make subnetworks from, for each node a dedicated
subnetwork will be generated
network_name : str, optional
network which contains the provided nodes,
by default CYTO_BASE_NETWORK_NAME
export_image : bool, optional
trigger image export of newly generated subnetworks, by default True
"""
logger.debug('Generating all subnetworks for node selection...')
for idx, node in enumerate(nodes_to_analyse):
select_neighbours_of_node(node=node, network_name=network_name)
make_subnetwork(index=idx, network_name=network_name, export_image=export_image)
logger.debug('Generation of all subnetworks for node selection successful.')