Beispiel #1
0
    def test_infer_data_type_empty_list(self):
        builder = NiceCXBuilder()

        self.assertEqual(([], 'list_of_string'), builder._infer_data_type([]))

        self.assertEqual(([], 'list_of_string'),
                         builder._infer_data_type([], split_string=True))
Beispiel #2
0
    def test_infer_data_type_bool(self):
        """
        Test added for bug: https://github.com/ndexbio/ndex2-client/issues/83
        :return:
        """
        builder = NiceCXBuilder()

        self.assertEqual((True, 'boolean'), builder._infer_data_type(True))

        self.assertEqual((True, 'boolean'),
                         builder._infer_data_type(True, split_string=True))
Beispiel #3
0
    def test_infer_data_type_list_of_integer(self):
        """
        Test added for bug: https://github.com/ndexbio/ndex2-client/issues/83
        :return:
        """
        builder = NiceCXBuilder()

        self.assertEqual(([1], 'list_of_integer'),
                         builder._infer_data_type([1]))

        self.assertEqual(([1], 'list_of_integer'),
                         builder._infer_data_type([1], split_string=True))
Beispiel #4
0
    def test_infer_data_type_str_split_is_false(self):
        builder = NiceCXBuilder()

        # empty string
        self.assertEqual(('', 'string'), builder._infer_data_type(''))

        # string with space
        self.assertEqual((' ', 'string'), builder._infer_data_type(' '))

        # simple string
        self.assertEqual(('foo', 'string'), builder._infer_data_type('foo'))

        # simple string with double quote
        self.assertEqual(('foo"', 'string'), builder._infer_data_type('foo"'))

        # string with comma delimiter, but split_string is left
        # to default which is False
        self.assertEqual(('item1,item2', 'string'),
                         builder._infer_data_type('item1,item2'))

        # string with comma delimiter, but split_string is left
        # to default which is False
        self.assertEqual(('item1;item2', 'string'),
                         builder._infer_data_type('item1;item2'))

        # string with comma and semicolon delimiter and double quote,
        # but split_string is left to default which is False
        self.assertEqual(('item1;item2,item3"', 'string'),
                         builder._infer_data_type('item1;item2,item3"'))
Beispiel #5
0
    def test_infer_data_type_int(self):
        """
        Test added for bug: https://github.com/ndexbio/ndex2-client/issues/83
        :return:
        """
        builder = NiceCXBuilder()

        self.assertEqual((1, 'integer'), builder._infer_data_type(1))

        self.assertEqual((1, 'integer'),
                         builder._infer_data_type(1, split_string=True))
        self.assertEqual((0, 'integer'), builder._infer_data_type(0))

        self.assertEqual((0, 'integer'),
                         builder._infer_data_type(0, split_string=True))

        self.assertEqual((-1, 'integer'), builder._infer_data_type(-1))

        self.assertEqual((-1, 'integer'),
                         builder._infer_data_type(-1, split_string=True))
Beispiel #6
0
def create_nice_cx_from_networkx(G):
    """
    Creates a :py:class:`~ndex2.nice_cx_network.NiceCXNetwork` based on a
    networkx graph.

    The resulting :py:class:`~ndex2.nice_cx_network.NiceCXNetwork`
    contains the nodes, edges and their attributes from the networkx graph and also
    preserves the graph 'pos' attribute as a CX cartesian coordinates aspect.

    The node name is taken from the networkx node id. Node 'represents' is
    taken from the networkx node attribute 'represents'

    :param G: networkx graph
    :type G: networkx graph
    :return: NiceCXNetwork
    :rtype: :py:class:`~ndex2.nice_cx_network.NiceCXNetwork`
    """

    niceCxBuilder = NiceCXBuilder()
    if G is None:
        raise Exception('Networkx input is empty')

    my_nicecx = NiceCXNetwork()

    if G.graph.get('name'):
        my_nicecx.set_name(G.graph.get('name'))
    else:
        my_nicecx.set_name('created from networkx')

    my_nicecx.add_metadata_stub('networkAttributes')

    #=========================================
    # Check to see if the node label is same
    # (case insensitive) as 'name' attribute
    #=========================================
    #use_node_label = False
    #for n, d in G.nodes_iter(data=True):
    #    if not isinstance(n, int) and d and d.get('name'):
    #        if n.lower() == d.get('name').lower():
    #            use_node_label = True

    #    break

    for n, d in G.nodes(data=True):
        # =============
        # ADD NODES
        # =============
        #if d and d.get('name'):
        #    if isinstance(n, int):
        #        node_id = niceCxBuilder.add_node(name=d.get('name'),represents=d.get('name'), id=n, map_node_ids=True)
        #    else:
        #        # If networkx node is of type string then maybe the 'name' atribute is no longer accurate
        #        if use_node_label:
        #            node_id = niceCxBuilder.add_node(name=n,represents=n, map_node_ids=True)
        #        else:
        #            node_id = niceCxBuilder.add_node(name=d.get('name'),represents=d.get('name'), map_node_ids=True)
        #else:
        if isinstance(n, int):
            node_id = niceCxBuilder.add_node(name=n,
                                             represents=d.get('represents'),
                                             id=n,
                                             map_node_ids=True)
        else:
            node_id = niceCxBuilder.add_node(name=n,
                                             represents=d.get('represents'),
                                             map_node_ids=True)

        # ======================
        # ADD NODE ATTRIBUTES
        # ======================
        for k, v in d.items():
            use_this_value, attr_type = niceCxBuilder._infer_data_type(
                v, split_string=True)

            if k == 'citation' and not isinstance(use_this_value, list):
                use_this_value = [use_this_value]
                attr_type = 'list_of_string'
            if use_this_value is not None:
                niceCxBuilder.add_node_attribute(node_id,
                                                 k,
                                                 use_this_value,
                                                 type=attr_type)

    index = 0
    for u, v, d in G.edges(data=True):
        # =============
        # ADD EDGES
        # =============
        if d.get('interaction') is None or d.get('interaction') == 'null':
            interaction = 'neighbor-of'
        else:
            interaction = d.get('interaction')

        if isinstance(u, int):
            niceCxBuilder.add_edge(source=u,
                                   target=v,
                                   interaction=interaction,
                                   id=index)
        else:
            niceCxBuilder.add_edge(source=niceCxBuilder.node_id_lookup.get(u),
                                   target=niceCxBuilder.node_id_lookup.get(v),
                                   interaction=interaction,
                                   id=index)

        # ==============================
        # ADD EDGE ATTRIBUTES
        # ==============================
        for k, val in d.items():
            if k != 'interaction':
                use_this_value, attr_type = niceCxBuilder._infer_data_type(
                    val, split_string=True)

                if k == 'citation' and not isinstance(use_this_value, list):
                    use_this_value = [use_this_value]
                    attr_type = 'list_of_string'

                if use_this_value is not None:
                    niceCxBuilder.add_edge_attribute(property_of=index,
                                                     name=k,
                                                     values=use_this_value,
                                                     type=attr_type)

        index += 1

    if hasattr(G, 'pos'):
        aspect = _create_cartesian_coordinates_aspect_from_networkx(G)
        niceCxBuilder.add_opaque_aspect('cartesianLayout', aspect)

    return niceCxBuilder.get_nice_cx()
Beispiel #7
0
    def test_infer_data_type_double(self):
        """
        Test added for bug: https://github.com/ndexbio/ndex2-client/issues/83
        :return:
        """
        builder = NiceCXBuilder()

        self.assertEqual((1.5, 'double'), builder._infer_data_type(1.5))

        self.assertEqual((1.5, 'double'),
                         builder._infer_data_type(1.5, split_string=True))
        self.assertEqual((0.0, 'double'), builder._infer_data_type(0.0))

        self.assertEqual((0.0, 'double'),
                         builder._infer_data_type(0.0, split_string=True))

        self.assertEqual((-1.0, 'double'), builder._infer_data_type(-1.0))

        self.assertEqual((-1.0, 'double'),
                         builder._infer_data_type(-1.0, split_string=True))

        self.assertEqual((-1.0, 'double'), builder._infer_data_type(-1.0))

        self.assertEqual((-1.0, 'double'),
                         builder._infer_data_type(-1.0, split_string=True))

        self.assertEqual((None, 'double'), builder._infer_data_type(math.nan))

        self.assertEqual((None, 'double'),
                         builder._infer_data_type(math.nan, split_string=True))
        self.assertEqual(('INFINITY', 'double'),
                         builder._infer_data_type(math.inf))

        self.assertEqual(('INFINITY', 'double'),
                         builder._infer_data_type(math.inf, split_string=True))
Beispiel #8
0
 def test_infer_data_type_none_val(self):
     builder = NiceCXBuilder()
     self.assertEqual((None, None), builder._infer_data_type(None))
Beispiel #9
0
def create_nice_cx_from_networkx(G):
    """
    Creates a NiceCXNetwork based on a networkx graph. The resulting NiceCXNetwork
    contains the nodes edges and their attributes from the networkx graph and also
    preserves the graph 'pos' attribute as a CX cartesian coordinates aspect.
    Node name is taken from the networkx node id. Node 'represents' is
    taken from the networkx node attribute 'represents'

    :param G: networkx graph
    :type G: networkx graph
    :return: NiceCXNetwork
    :rtype: NiceCXNetwork
    """

    niceCxBuilder = NiceCXBuilder()
    if G is None:
        raise Exception('Networkx input is empty')

    my_nicecx = NiceCXNetwork()

    if G.graph.get('name'):
        my_nicecx.set_name(G.graph.get('name'))
    else:
        my_nicecx.set_name('created from networkx')

    my_nicecx.add_metadata_stub('networkAttributes')


    #=========================================
    # Check to see if the node label is same
    # (case insensitive) as 'name' attribute
    #=========================================
    #use_node_label = False
    #for n, d in G.nodes_iter(data=True):
    #    if not isinstance(n, int) and d and d.get('name'):
    #        if n.lower() == d.get('name').lower():
    #            use_node_label = True

    #    break

    for n, d in G.nodes(data=True):
        # =============
        # ADD NODES
        # =============
        #if d and d.get('name'):
        #    if isinstance(n, int):
        #        node_id = niceCxBuilder.add_node(name=d.get('name'),represents=d.get('name'), id=n, map_node_ids=True)
        #    else:
        #        # If networkx node is of type string then maybe the 'name' atribute is no longer accurate
        #        if use_node_label:
        #            node_id = niceCxBuilder.add_node(name=n,represents=n, map_node_ids=True)
        #        else:
        #            node_id = niceCxBuilder.add_node(name=d.get('name'),represents=d.get('name'), map_node_ids=True)
        #else:
        if isinstance(n, int):
            node_id = niceCxBuilder.add_node(name=n,represents=d.get('represents'), id=n, map_node_ids=True)
        else:
            node_id = niceCxBuilder.add_node(name=n, represents=d.get('represents'), map_node_ids=True)

        # ======================
        # ADD NODE ATTRIBUTES
        # ======================
        for k, v in d.items():
            use_this_value, attr_type = niceCxBuilder._infer_data_type(v, split_string=True)

            if k == 'citation' and not isinstance(use_this_value, list):
                use_this_value = [use_this_value]
                attr_type = 'list_of_string'
            if use_this_value is not None:
                niceCxBuilder.add_node_attribute(node_id, k, use_this_value, type=attr_type)

    index = 0
    for u, v, d in G.edges(data=True):
        # =============
        # ADD EDGES
        # =============
        if d.get('interaction') is None or d.get('interaction') == 'null':
            interaction = 'neighbor-of'
        else:
            interaction = d.get('interaction')

        if isinstance(u, int):
            niceCxBuilder.add_edge(source=u, target=v, interaction=interaction, id=index)
        else:
            niceCxBuilder.add_edge(source=niceCxBuilder.node_id_lookup.get(u), target=niceCxBuilder.node_id_lookup.get(v),
                               interaction=interaction, id=index)

        # ==============================
        # ADD EDGE ATTRIBUTES
        # ==============================
        for k, val in d.items():
            if k != 'interaction':
                use_this_value, attr_type = niceCxBuilder._infer_data_type(val, split_string=True)

                if k == 'citation' and not isinstance(use_this_value, list):
                    use_this_value = [use_this_value]
                    attr_type = 'list_of_string'

                if use_this_value is not None:
                    niceCxBuilder.add_edge_attribute(property_of=index, name=k, values=use_this_value, type=attr_type)

        index += 1

    if hasattr(G, 'pos'):
        aspect = _create_cartesian_coordinates_aspect_from_networkx(G)
        niceCxBuilder.add_opaque_aspect('cartesianLayout', aspect)

    return niceCxBuilder.get_nice_cx()
Beispiel #10
0
def create_nice_cx_from_networkx(G):
    """
    Creates a :py:class:`~ndex2.nice_cx_network.NiceCXNetwork` based on a
    :class:`networkx.Graph` graph.

    .. versionchanged:: 3.5.0
       Major refactor to fix multiple bugs #83, #84, #90

    .. code-block:: python

        import ndex2
        import networkx as nx

        G = nx.Graph()
        G.add_node(1, someval=1.5, name='node 1')
        G.add_node(2, someval=2.5, name='node 2')
        G.add_edge(1, 2, weight=5)

        print(ndex2.create_nice_cx_from_networkx(G).to_cx())

    The resulting :py:class:`~ndex2.nice_cx_network.NiceCXNetwork`
    contains the nodes, edges and their attributes from the
    :class:`networkx.Graph`
    graph and also preserves the graph 'pos' attribute as a CX
    cartesian coordinates aspect
    :py:const:`~ndex2.constants.CARTESIAN_LAYOUT_ASPECT`
    with the values of `Y` inverted

    Description of how conversion is performed:

    **Network:**

    * Network name is set value of ``G.graph.get('name')`` or to
      ``created from networkx by ndex2.create_nice_cx_networkx()`` if
      `name` is ``None`` or not present

    **Nodes:**

    * Node id is value of ``n`` from this for loop:
      ``for n, d G.nodes(data=True):`` if ``n`` is **NOT** an
      :py:class:`int`, new ids starting from ``0`` are used

    * Node name is value of `name` attribute on the node or is
      set to id of node if `name` is not present.

    * Node `represents` is value of `represents` attribute on the
      node or set is to node `name` if ``None`` or not present

    **Edges:**

    * Interaction is value of `interaction` attribute on the edge
      or is set to ``neighbor-of`` if ``None`` or not present

    .. note::

        Data types are inferred by using :py:func:`isinstance` and
        converted to corresponding CX data types. For list items,
        only the 1st item is examined to determine type

    :param G: Graph to convert
    :type G: :class:`networkx.Graph`
    :raises Exception: if **G** parameter is ``None`` or there is another error
                       in conversion
    :return: Converted network
    :rtype: :py:class:`~ndex2.nice_cx_network.NiceCXNetwork`
    """
    cx_builder = NiceCXBuilder()
    if G is None:
        raise Exception('Networkx input is empty')

    network_name = G.graph.get('name')
    if network_name is not None:
        cx_builder.set_name(network_name)
    else:
        cx_builder.set_name('created from networkx by '
                            'ndex2.create_nice_cx_networkx()')

    for n, d in G.nodes(data=True):
        if isinstance(n, int):
            n_name = d.get('name')
            if n_name is None:
                n_name = str(n)
            node_id = cx_builder.add_node(name=n_name,
                                          represents=d.get('represents'),
                                          id=n,
                                          map_node_ids=True)
        else:
            node_id = cx_builder.add_node(name=n,
                                          represents=d.get('represents'),
                                          map_node_ids=True)

        # ======================
        # ADD NODE ATTRIBUTES
        # ======================
        for k, v in d.items():

            # if node attribute is 'name' skip it cause that will be used
            # for name of node, also skip 'represents'
            # fix for https://github.com/ndexbio/ndex2-client/issues/84
            if k == 'name' or k == 'represents':
                continue

            use_this_value, attr_type = cx_builder._infer_data_type(
                v, split_string=False)

            # This might go away, waiting on response to
            # https://ndexbio.atlassian.net/browse/UD-2181
            if k == 'citation' and not isinstance(use_this_value, list):
                use_this_value = [str(use_this_value)]
                attr_type = constants.LIST_OF_STRING
            if use_this_value is not None:
                cx_builder.add_node_attribute(node_id,
                                              k,
                                              use_this_value,
                                              type=attr_type)

    index = 0
    for u, v, d in G.edges(data=True):
        # =============
        # ADD EDGES
        # =============
        if d.get('interaction') is None or d.get('interaction') == 'null':
            interaction = 'neighbor-of'
        else:
            interaction = d.get('interaction')

        if isinstance(u, int):
            cx_builder.add_edge(source=u,
                                target=v,
                                interaction=interaction,
                                id=index)
        else:
            cx_builder.add_edge(source=cx_builder.node_id_lookup.get(u),
                                target=cx_builder.node_id_lookup.get(v),
                                interaction=interaction,
                                id=index)

        # ==============================
        # ADD EDGE ATTRIBUTES
        # ==============================
        for k, val in d.items():
            if k == 'interaction':
                continue
            use_this_value, attr_type = cx_builder._infer_data_type(
                val, split_string=False)

            # This might go away, waiting on response to
            # https://ndexbio.atlassian.net/browse/UD-2181
            if k == 'citation' and not isinstance(use_this_value, list):
                use_this_value = [str(use_this_value)]
                attr_type = constants.LIST_OF_STRING

            if use_this_value is not None:
                cx_builder.add_edge_attribute(property_of=index,
                                              name=k,
                                              values=use_this_value,
                                              type=attr_type)

        index += 1

    if hasattr(G, 'pos'):
        aspect = _create_cartesian_coordinates_aspect_from_networkx(G)
        cx_builder.add_opaque_aspect(constants.CARTESIAN_LAYOUT_ASPECT, aspect)

    return cx_builder.get_nice_cx()