class_docstr: Graph drawer that sends/receives graphs to/from Cytoscape using
  CytoscapeRPC.
  
  This graph drawer cooperates with U{Cytoscape<http://www.cytoscape.org>}
  using U{CytoscapeRPC<http://wiki.nbic.nl/index.php/CytoscapeRPC>}.
  You need to install the CytoscapeRPC plugin first and start the
  XML-RPC server on a given port (port 9000 by default) from the
  appropriate Plugins submenu in Cytoscape.
  
  Graph, vertex and edge attributes are transferred to Cytoscape whenever
  possible (i.e. when a suitable mapping exists between a Python type
  and a Cytoscape type). If there is no suitable Cytoscape type for a
  Python type, the drawer will use a string attribute on the Cytoscape
  side and invoke C{str()} on the Python attributes.
  
  If an attribute to be created on the Cytoscape side already exists with
  a different type, an underscore will be appended to the attribute name
  to resolve the type conflict.
  
  You can use the C{network_id} attribute of this class to figure out the
  network ID of the last graph drawn with this drawer.
docstr: Sends the given graph to Cytoscape as a new network.
  
  @param name: the name of the network in Cytoscape.
  @param create_view: whether to create a view for the network
    in Cytoscape.The default is C{True}.
  @keyword node_ids: specifies the identifiers of the nodes to
    be used in Cytoscape. This must either be the name of a
    vertex attribute or a list specifying the identifiers, one
    for each node in the graph. The default is C{None}, which
    simply uses the vertex index for each vertex.
docstr_tok: ["Sends","the","given","graph","to","Cytoscape","as","a","new","network",".","@","param","name",":","the","name","of","the","network","in","Cytoscape",".","@","param","create_view",":","whether","to","create","a","view","for","the","network","in","Cytoscape.The","default","is","C","{","True","}",".","@","keyword","node_ids",":","specifies","the","identifiers","of","the","nodes","to","be","used","in","Cytoscape",".","This","must","either","be","the","name","of","a","vertex","attribute","or","a","list","specifying","the","identifiers",",","one","for","each","node","in","the","graph",".","The","default","is","C","{","None","}",",","which","simply","uses","the","vertex","index","for","each","vertex","."]
code: def draw(
      self,
      graph,
      name="Network from igraph",
      create_view=True,
      *args,
      **kwds,
  ):
      """Sends the given graph to Cytoscape as a new network.
  
      @param name: the name of the network in Cytoscape.
      @param create_view: whether to create a view for the network
        in Cytoscape.The default is C{True}.
      @keyword node_ids: specifies the identifiers of the nodes to
        be used in Cytoscape. This must either be the name of a
        vertex attribute or a list specifying the identifiers, one
        for each node in the graph. The default is C{None}, which
        simply uses the vertex index for each vertex."""
      from xmlrpc.client import Fault
  
      # Positional arguments are not used
      if args:
          warn(
              "Positional arguments to plot functions are ignored "
              "and will be deprecated soon.",
              DeprecationWarning,
              stacklevel=1,
          )
  
      cy = self.service
  
      # Create the network
      if not create_view:
          try:
              network_id = cy.createNetwork(name, False)
          except Fault:
              warn(
                  "CytoscapeRPC too old, cannot create network without view."
                  " Consider upgrading CytoscapeRPC to use this feature.",
                  stacklevel=1,
              )
              network_id = cy.createNetwork(name)
      else:
          network_id = cy.createNetwork(name)
      self.network_id = network_id
  
      # Create the nodes
      if "node_ids" in kwds:
          node_ids = kwds["node_ids"]
          if isinstance(node_ids, str):
              node_ids = graph.vs[node_ids]
      else:
          node_ids = list(range(graph.vcount()))
      node_ids = [str(identifier) for identifier in node_ids]
      cy.createNodes(network_id, node_ids)
  
      # Create the edges
      edgelists = [[], []]
      for v1, v2 in graph.get_edgelist():
          edgelists[0].append(node_ids[v1])
          edgelists[1].append(node_ids[v2])
      edge_ids = cy.createEdges(
          network_id,
          edgelists[0],
          edgelists[1],
          ["unknown"] * graph.ecount(),
          [graph.is_directed()] * graph.ecount(),
          False,
      )
  
      if "layout" in kwds:
          # Calculate/get the layout of the graph
          layout = self.ensure_layout(kwds["layout"], graph)
          size = 100 * graph.vcount() ** 0.5
          layout.fit_into((size, size), keep_aspect_ratio=True)
          layout.translate(-size / 2.0, -size / 2.0)
          cy.setNodesPositions(
              network_id, node_ids, *list(zip(*list(layout)))
          )
      else:
          # Ask Cytoscape to perform the default layout so the user can
          # at least see something in Cytoscape while the attributes are
          # being transferred
          cy.performDefaultLayout(network_id)
  
      # Send the network attributes
      attr_names = set(cy.getNetworkAttributeNames())
      for attr in graph.attributes():
          cy_type, value = self.infer_cytoscape_type([graph[attr]])
          value = value[0]
          if value is None:
              continue
  
          # Resolve type conflicts (if any)
          try:
              while (
                  attr in attr_names
                  and cy.getNetworkAttributeType(attr) != cy_type
              ):
                  attr += "_"
          except Fault:
              # getNetworkAttributeType is not available in some older versions
              # so we simply pass here
              pass
          cy.addNetworkAttributes(attr, cy_type, {network_id: value})
  
      # Send the node attributes
      attr_names = set(cy.getNodeAttributeNames())
      for attr in graph.vertex_attributes():
          cy_type, values = self.infer_cytoscape_type(graph.vs[attr])
          values = dict(
              pair
              for pair in zip(node_ids, values)
              if pair[1] is not None
          )
          # Resolve type conflicts (if any)
          while (
              attr in attr_names
              and cy.getNodeAttributeType(attr) != cy_type
          ):
              attr += "_"
          # Send the attribute values
          cy.addNodeAttributes(attr, cy_type, values, True)
  
      # Send the edge attributes
      attr_names = set(cy.getEdgeAttributeNames())
      for attr in graph.edge_attributes():
          cy_type, values = self.infer_cytoscape_type(graph.es[attr])
          values = dict(
              pair
              for pair in zip(edge_ids, values)
              if pair[1] is not None
          )
          # Resolve type conflicts (if any)
          while (
              attr in attr_names
              and cy.getEdgeAttributeType(attr) != cy_type
          ):
              attr += "_"
          # Send the attribute values
          cy.addEdgeAttributes(attr, cy_type, values)
  
file_path: python-igraph/src/igraph/drawing/graph.py
imports: from warnings import warn
  from igraph.drawing.baseclasses import AbstractGraphDrawer, AbstractXMLRPCDrawer
label_desc: Use image node_id 2 for calling the CytoscapeGraphDrawer obj's underlying member method code with example usage: obj.draw(graph, name, create_view) without return types