# lang_main.render.cytoscape API documentation

# 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 error

  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
`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 error

  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
`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