Module lang_main.render.cytoscape
Functions
def analyse_network(property_degree_weighted: str = 'degree_weighted',
network_name: str = 'token_graph') ‑> None-
Expand source code
def analyse_network( property_degree_weighted: str = PROPERTY_NAME_DEGREE_WEIGHTED, network_name: str = CYTO_BASE_NETWORK_NAME, ) -> None: node_table = p4c.get_table_columns(table='node', network=network_name) net_analyse_possible: bool = True if len(node_table) < 4: # pragma: no cover net_analyse_possible = False if net_analyse_possible: p4c.analyze_network(directed=False) node_table = p4c.get_table_columns(table='node', network=network_name) node_table['stress_norm'] = node_table['Stress'] / node_table['Stress'].max() node_table[CYTO_SELECTION_PROPERTY] = ( node_table[property_degree_weighted] * node_table['BetweennessCentrality'] * node_table['stress_norm'] ) else: # pragma: no cover node_table[CYTO_SELECTION_PROPERTY] = 1 p4c.load_table_data(node_table, data_key_column='name', network=network_name) def apply_style_to_network(style_name: str = 'lang_main',
pth_to_stylesheet: pathlib.Path = WindowsPath('A:/Arbeitsaufgaben/lang-main/src/lang_main/cytoscape_config/lang_main.xml'),
network_name: str = 'token_graph',
node_size_property: str = 'node_selection',
min_node_size: int = 15,
max_node_size: int = 40,
sandbox_name: str = 'lang_main') ‑> None-
Expand source code
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, node_size_property: str = CYTO_SELECTION_PROPERTY, min_node_size: int = 15, max_node_size: int = 40, sandbox_name: str = CYTO_SANDBOX_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()) logger.debug('Available styles: %s', styles_avail) if style_name not in styles_avail: if not pth_to_stylesheet.exists(): # existence for standard path verified at import, but not for other # provided paths raise FileNotFoundError( f'Visual stylesheet for Cytoscape not found under: >>{pth_to_stylesheet}<<' ) # send to sandbox sandbox_filename = pth_to_stylesheet.name p4c.sandbox_send_to( source_file=pth_to_stylesheet, dest_file=sandbox_filename, overwrite=True, sandbox_name=sandbox_name, ) # load stylesheet p4c.import_visual_styles(sandbox_filename) p4c.set_visual_style(style_name, network=network_name) # node size mapping, only if needed property is available scheme = p4c.scheme_c_number_continuous( start_value=min_node_size, end_value=max_node_size ) node_size_map = p4c.gen_node_size_map( node_size_property, number_scheme=scheme, mapping_type='c', style_name=style_name, default_number=min_node_size, ) p4c.set_node_size_mapping(**node_size_map) fit_content(network_name=network_name) logger.debug('Style application to network successful.')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
def build_subnetworks(nodes_to_analyse: Iterable[int],
network_name: str = 'token_graph',
export_image: bool = True,
target_folder: pathlib.Path = WindowsPath('A:/Arbeitsaufgaben/lang-data/out')) ‑> None-
Expand source code
def build_subnetworks( nodes_to_analyse: Iterable[CytoNodeID], network_name: str = CYTO_BASE_NETWORK_NAME, export_image: bool = True, target_folder: Path = SAVE_PATH_FOLDER, ) -> 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, target_folder=target_folder, ) logger.debug('Generation of all subnetworks for node selection successful.')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
def change_default_layout() ‑> None-
Expand source code
def change_default_layout() -> None: """Cytoscape: resets the default layout to `grid` to accelerate the import process (grid layout one of the fastest) Raises ------ RequestException API endpoint not reachable or CyREST operation not successful """ body: dict[str, str] = {'value': 'grid', 'key': 'layout.default'} try: p4c.cyrest_put('properties/cytoscape3.props/layout.default', body=body) except RequestException as error: logger.error('[CytoAPIConnection] Property change of default layout not successful.') raise errorCytoscape: resets the default layout to
gridto accelerate the import process (grid layout one of the fastest)Raises
RequestException- API endpoint not reachable or CyREST operation not successful
def export_network_to_image(filename: str,
target_folder: pathlib.Path = WindowsPath('A:/Arbeitsaufgaben/lang-data/out'),
filetype: Literal['JPEG', 'PDF', 'PNG', 'PS', 'SVG'] = 'SVG',
network_name: str = 'token_graph',
pdf_export_page_size: Literal['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'Auto', 'Legal', 'Letter', 'Tabloid'] = 'A4',
sandbox_name: str = 'lang_main') ‑> None-
Expand source code
def export_network_to_image( filename: str, target_folder: Path = SAVE_PATH_FOLDER, filetype: CytoExportFileTypes = 'SVG', network_name: str = CYTO_BASE_NETWORK_NAME, pdf_export_page_size: CytoExportPageSizes = 'A4', sandbox_name: str = CYTO_SANDBOX_NAME, ) -> None: """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...') if not target_folder.exists(): # pragma: no cover target_folder.mkdir(parents=True) dst_file_pth = (target_folder / filename).with_suffix(f'.{filetype.lower()}') text_as_font = True if filetype == 'SVG': text_as_font = False # close non-necessary windows and fit graph in frame before image display fit_content(network_name=network_name) # image is generated in sandbox directory and transferred to target destination # (preparation for remote instances of Cytoscape) p4c.export_image( filename=filename, type=filetype, network=network_name, overwrite_file=True, all_graphics_details=True, export_text_as_font=text_as_font, page_size=pdf_export_page_size, ) logger.debug('Exported image to sandbox.') logger.debug('Transferring image from sandbox to target destination...') sandbox_filename = f'{filename}.{filetype.lower()}' p4c.sandbox_get_from( source_file=sandbox_filename, dest_file=str(dst_file_pth), overwrite=True, sandbox_name=sandbox_name, ) logger.debug('Transfer of image from sandbox to target destination successful.')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'
def fit_content(zoom_factor: float = 0.96, network_name: str = 'token_graph') ‑> None-
Expand source code
def fit_content( zoom_factor: float = CYTO_NETWORK_ZOOM_FACTOR, network_name: str = CYTO_BASE_NETWORK_NAME, ) -> None: p4c.hide_all_panels() p4c.fit_content(selected_only=False, network=network_name) zoom_current = p4c.get_network_zoom(network=network_name) zoom_new = zoom_current * zoom_factor p4c.set_network_zoom_bypass(zoom_new, bypass=False, network=network_name) def get_subgraph_node_selection(network_name: str = 'token_graph', num_subgraphs: int = 5) ‑> list[int]-
Expand source code
def get_subgraph_node_selection( network_name: str = CYTO_BASE_NETWORK_NAME, 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(table='node', network=network_name) node_table = node_table.sort_values(by=CYTO_SELECTION_PROPERTY, ascending=False) p4c.load_table_data(node_table, data_key_column='name', network=network_name) node_table_choice = node_table.iloc[:num_subgraphs] logger.debug('Selection of nodes for subgraph generation successful.') return node_table_choice['SUID'].to_list()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
def import_to_cytoscape(graph: networkx.classes.digraph.DiGraph | networkx.classes.graph.Graph,
network_name: str = 'token_graph',
sandbox_name: str = 'lang_main',
reinitialise_sandbox: bool = True) ‑> None-
Expand source code
def import_to_cytoscape( graph: DiGraph | Graph, network_name: str = CYTO_BASE_NETWORK_NAME, sandbox_name: str = CYTO_SANDBOX_NAME, reinitialise_sandbox: bool = True, ) -> 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('Checking graph size for rendering...') verify_graph_render_size(graph) logger.debug('Setting default layout to improve import speed...') change_default_layout() logger.debug('Setting Cytoscape sandbox...') p4c.sandbox_set( sandbox_name=sandbox_name, reinitialize=reinitialise_sandbox, copy_samples=False, ) logger.debug('Importing to and analysing network in Cytoscape...') p4c.delete_all_networks() p4c.create_network_from_networkx( graph, title=network_name, collection=CYTO_COLLECTION_NAME, ) analyse_network(network_name=network_name) logger.debug('Import and analysis of network to Cytoscape successful.')Cytoscape: import NetworkX graph as new network collection
Parameters
graph:DiGraph | Graph- NetworkX graph object
def layout_network(layout_name: Literal['attribute-circle', 'attribute-grid', 'attributes-layout', 'circular', 'cose', 'degree-circle', 'force-directed', 'force-directed-cl', 'fruchterman-rheingold', 'grid', 'hierarchical', 'isom', 'kamada-kawai', 'stacked-node-layout'] = 'force-directed',
layout_properties: dict[str, float | bool] = {'numIterations': 1000, 'defaultSpringCoefficient': 0.0001, 'defaultSpringLength': 45, 'defaultNodeMass': 11, 'isDeterministic': True, 'singlePartition': False},
network_name: str = 'token_graph') ‑> None-
Expand source code
def layout_network( layout_name: CytoLayouts = CYTO_LAYOUT_NAME, 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) fit_content(network_name=network_name) logger.debug('Layout application to network successful.')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
def make_subnetwork(index: int,
network_name: str = 'token_graph',
export_image: bool = True,
target_folder: pathlib.Path = WindowsPath('A:/Arbeitsaufgaben/lang-data/out')) ‑> None-
Expand source code
def make_subnetwork( index: int, network_name: str = CYTO_BASE_NETWORK_NAME, export_image: bool = True, target_folder: Path = SAVE_PATH_FOLDER, ) -> 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', edges='selected', subnetwork_name=subnetwork_name, network=network_name, ) p4c.set_current_network(subnetwork_name) if export_image: time.sleep(1) export_network_to_image( filename=subnetwork_name, target_folder=target_folder, network_name=subnetwork_name, ) logger.debug('Generation of subnetwork with index %d successful.', index)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
def reset_current_network_to_base() ‑> None-
Expand source code
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)resets to currently selected network in Cytoscape back to the base one
def select_neighbours_of_node(node: int, neighbour_iter_depth: int = 2, network_name: str = 'token_graph') ‑> None-
Expand source code
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(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)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
def verify_connection() ‑> None-
Expand source code
def verify_connection() -> None: """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: # pragma: no cover logger.error('[CyError] CyREST or Cytoscape version not supported.') raise error except RequestException as error: logger.error('[CytoAPIConnection] Connection to CyREST API failed.') raise errorCytoscape: 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
def verify_graph_render_size(graph: networkx.classes.digraph.DiGraph | networkx.classes.graph.Graph,
max_node_count: int | None = 500,
max_edge_count: int | None = 800) ‑> None-
Expand source code
def verify_graph_render_size( graph: Graph | DiGraph, max_node_count: int | None = CYTO_MAX_NODE_COUNT, max_edge_count: int | None = CYTO_MAX_EDGE_COUNT, ) -> None: """verify that the graph size can still be handled within an acceptable time frame for rendering in Cytoscape Parameters ---------- graph : Graph | DiGraph graph to verify max_node_count : int | None, optional maximum allowed number of nodes, by default CYTO_MAX_NODE_COUNT max_edge_count : int | None, optional maximum allowed number of edges, by default CYTO_MAX_EDGE_COUNT Raises ------ GraphRenderError if any of the provided limits is exceeded """ num_nodes = len(graph.nodes) num_edges = len(graph.edges) if max_node_count is not None and num_nodes > max_node_count: raise GraphRenderError( f'Maximum number of nodes for rendering exceeded. ' f'Limit {max_node_count}, Counted: {num_nodes}' ) if max_edge_count is not None and num_edges > max_edge_count: raise GraphRenderError( f'Maximum number of edges for rendering exceeded. ' f'Limit {max_edge_count}, Counted: {num_edges}' )verify that the graph size can still be handled within an acceptable time frame for rendering in Cytoscape
Parameters
graph:Graph | DiGraph- graph to verify
max_node_count:int | None, optional- maximum allowed number of nodes, by default CYTO_MAX_NODE_COUNT
max_edge_count:int | None, optional- maximum allowed number of edges, by default CYTO_MAX_EDGE_COUNT
Raises
GraphRenderError- if any of the provided limits is exceeded
def verify_table_property(property: str,
table_type: Literal['node', 'edge', 'network'] = 'node',
network_name: str = 'token_graph') ‑> bool-
Expand source code
def verify_table_property( property: str, table_type: Literal['node', 'edge', 'network'] = 'node', network_name: str = CYTO_BASE_NETWORK_NAME, ) -> bool: table = p4c.get_table_columns(table=table_type, network=network_name) logger.debug('Table >>%s<< wiht columns: %s', table, table.columns) return property in table.columns