Ejemplo n.º 1
0
def get_nd_regular_graph(shape, neighbour_list):
    """
    Creates a regular graph of the given :attr:`shape` with the adjacency given as a
    :attr:`neighbour_list`.

    See the helper function :func:`~higra.mask_2_neighbours` to create a suitable :attr:`neighbour_list`.

    :Example:

    Create a 2d 4-adjacency implicit graph of size ``(13, 24)``:

    >>> graph = get_nd_regular_graph((13, 24), ((-1, 0), (0, -1), (0, 1), (1, 0)))

    Create a 3d 6-adjacency implicit graph of size ``(10, 13, 24)``:

    >>> mask = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    >>>         [[0, 1, 0], [1, 0, 1], [0, 1, 0]],
    >>>         [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]
    >>> neighbours = mask_2_neighbours(mask)
    >>> graph = get_nd_regular_graph((10, 13, 24), neighbours)

    :param shape: a tuple of :math:`n` elements representing the dimension of the graph vertices.
    :param neighbour_list: a 2d array of :math:`k` :math:`n`-d integer vectors
    :return: a regular graph
    """

    graph_implicit = get_nd_regular_implicit_graph(shape, neighbour_list)
    graph = graph_implicit.as_explicit_graph()

    hg.CptGridGraph.link(graph, hg.CptGridGraph.get_shape(graph_implicit))
    hg.set_attribute(
        graph, "no_border_vertex_out_degree",
        hg.get_attribute(graph_implicit, "no_border_vertex_out_degree"))

    return graph
Ejemplo n.º 2
0
    def test_pickle(self):
        import pickle

        tests = ((hg.RegularGraph1d, (3, ), ((-1, ), (1, ))),
                 (hg.RegularGraph2d, (3, 2), ((-1, 0), (1, 0))),
                 (hg.RegularGraph3d, (3, 2, 1),
                  ((-1, 0, -1), (1, 0, 1))), (hg.RegularGraph4d, (3, 2, 1, 2),
                                              ((-1, 0, -1, 0), (1, 0, 1, 0))),
                 (hg.RegularGraph5d, (3, 2, 1, 2, 1), ((-1, 0, -1, 0, 1),
                                                       (1, 0, 1, 0, -1))))

        for c, s, n in tests:
            e = c(s, n)
            hg.set_attribute(e, "test", (1, 2, 3))
            hg.add_tag(e, "foo")

            data = pickle.dumps(e)
            e2 = pickle.loads(data)

            self.assertTrue(np.all(e.shape() == e2.shape()))
            self.assertTrue(np.all(e.neighbour_list() == e2.neighbour_list()))

            self.assertTrue(
                hg.get_attribute(e, "test") == hg.get_attribute(e2, "test"))
            self.assertTrue(e.test == e2.test)
            self.assertTrue(hg.has_tag(e2, "foo"))
Ejemplo n.º 3
0
 def test_vertex_perimeter2(self):
     g = hg.get_4_adjacency_graph((2, 3))
     hg.set_attribute(g, "no_border_vertex_out_degree", None)
     ref = np.asarray(((2, 3, 2),
                       (2, 3, 2)))
     res = hg.attribute_vertex_perimeter(g)
     self.assertTrue(np.allclose(ref, res))
Ejemplo n.º 4
0
def get_nd_regular_implicit_graph(shape, neighbour_list):
    """
    Creates an implicit regular graph of the given :attr:`shape` with the adjacency given as a
    :attr:`neighbour_list`.

    See the helper function :func:`~higra.mask_2_neighbours` to create a suitable :attr:`neighbour_list`.

    :Example:

    Create a 2d 4-adjacency implicit graph of size ``(13, 24)``:

    >>> graph = get_nd_regular_implicit_graph((13, 24), ((-1, 0), (0, -1), (0, 1), (1, 0)))

    Create a 3d 6-adjacency implicit graph of size ``(10, 13, 24)``:

    >>> mask = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]],
    >>>         [[0, 1, 0], [1, 0, 1], [0, 1, 0]],
    >>>         [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]
    >>> neighbours = mask_2_neighbours(mask)
    >>> graph = get_nd_regular_implicit_graph((10, 13, 24), neighbours)

    :param shape: a tuple of :math:`n` elements representing the dimension of the graph vertices.
    :param neighbour_list: a 2d array of :math:`k` :math:`n`-d integer vectors
    :return: an implicit regular graph
    """

    neighbour_list = np.asarray(neighbour_list)

    if not np.issubdtype(neighbour_list.dtype, np.integer):
        raise ValueError("'neighbour_list' must be of integral type.")

    if neighbour_list.ndim != 2:
        raise ValueError("'neighbour_list' must be a 2d array.")

    shape = hg.normalize_shape(shape)

    if len(shape) != neighbour_list.shape[1]:
        raise ValueError(
            "Shape size does not match provided adjacency dimension.")

    if len(shape) > 5 or len(shape) == 0:
        raise ValueError("Shape size must between 1 and 5 (included).")

    if len(shape) == 1:
        graph = hg.RegularGraph1d(shape, neighbour_list)
    elif len(shape) == 2:
        graph = hg.RegularGraph2d(shape, neighbour_list)
    elif len(shape) == 3:
        graph = hg.RegularGraph3d(shape, neighbour_list)
    elif len(shape) == 4:
        graph = hg.RegularGraph4d(shape, neighbour_list)
    elif len(shape) == 5:
        graph = hg.RegularGraph5d(shape, neighbour_list)

    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree",
                     neighbour_list.shape[0])

    return graph
Ejemplo n.º 5
0
 def test_consumer_compoundPath(self):
     obj7 = Dummy(7)
     obj8 = Dummy(8)
     self.assertRaises(Exception, consumer3, obj7)
     hg.set_attribute(obj7, "dep", obj8)
     self.assertTrue(consumer3(obj7) == 3)
     self.assertTrue(hg.get_attribute(obj8, "attr2") == 2)
     self.assertTrue(hg.get_attribute(obj8, "attr1") == 1)
     hg.clear_all_attributes()
Ejemplo n.º 6
0
 def test_contour_length_partition_tree2(self):
     tree, altitudes = TestAttributes.get_test_tree()
     hg.set_attribute(hg.CptHierarchy.get_leaf_graph(tree),
                      "no_border_vertex_out_degree", None)
     ref_attribute = np.asarray(
         [2, 3, 2, 3, 4, 3, 2, 3, 2, 3, 3, 5, 3, 3, 4, 5, 0],
         dtype=np.float64)
     attribute = hg.attribute_contour_length(tree)
     self.assertTrue(np.allclose(ref_attribute, attribute))
Ejemplo n.º 7
0
def get_8_adjacency_implicit_graph(shape):
    """
    Create an implicit undirected 8 adjacency graph of the given shape (edges are not stored).

    :param shape: a pair (height, width)
    :return: a graph (Concept :class:`~higra.CptGridGraph`)
    """
    shape = hg.normalize_shape(shape)
    graph = hg.cpp._get_8_adjacency_implicit_graph(shape)
    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree", 8)

    return graph
Ejemplo n.º 8
0
    def get_mst(tree):
        """
        The minimum spanning tree of the leaf graph of the hierarchy.

        :param tree:
        :return:
        """
        mst = hg.get_attribute(tree, "mst")
        if mst is None:
            mst_edge_map = hg.CptBinaryHierarchy.get_mst_edge_map(tree)
            leaf_graph = hg.CptHierarchy.get_leaf_graph(tree)
            mst = hg.subgraph(leaf_graph, mst_edge_map, spanning=True)
            hg.CptMinimumSpanningTree.link(mst, leaf_graph, mst_edge_map)
            hg.set_attribute(tree, "mst", mst)
        return mst
Ejemplo n.º 9
0
def read_tree(filename):
    """
    Read a tree stored in mixed ascii/binary format.

    Attributes are also registered as tree object attributes.

    :param filename: path to the tree file
    :return: a pair (tree, attribute_map)
    """
    tree, attribute_map = hg.cpp._read_tree(filename)

    for k in attribute_map:
        hg.set_attribute(tree, k, attribute_map[k])

    return tree, attribute_map
Ejemplo n.º 10
0
    def test_contour_strength_partition_tree2(self):
        tree, altitudes = TestAttributes.get_test_tree()
        edge_weights = np.asarray((0, 6, 2, 6, 0, 0, 5, 4, 5, 3, 0, 1),
                                  dtype=np.float64)
        hg.set_attribute(hg.CptHierarchy.get_leaf_graph(tree),
                         "no_border_vertex_out_degree", None)
        attribute = hg.attribute_contour_strength(tree, edge_weights)

        ref_perimeter = np.asarray(
            [2, 3, 2, 3, 4, 3, 2, 3, 2, 3, 3, 5, 3, 3, 4, 5, 1],
            dtype=np.float64)
        ref_weights = np.asarray(
            [6, 8, 2, 11, 15, 7, 5, 6, 4, 14, 9, 26, 11, 13, 19, 26, 0],
            dtype=np.float64)
        self.assertTrue(np.allclose(ref_weights / ref_perimeter, attribute))
Ejemplo n.º 11
0
def get_4_adjacency_graph(shape):
    """
    Create an explicit undirected 4 adjacency graph of the given shape.

    :param shape: a pair (height, width)
    :return: a graph (Concept :class:`~higra.CptGridGraph`)
    """
    graph_implicit = get_4_adjacency_implicit_graph(shape)
    graph = graph_implicit.as_explicit_graph()

    hg.CptGridGraph.link(graph, hg.CptGridGraph.get_shape(graph_implicit))
    hg.set_attribute(
        graph, "no_border_vertex_out_degree",
        hg.get_attribute(graph_implicit, "no_border_vertex_out_degree"))

    return graph
Ejemplo n.º 12
0
def khalimsky_2_graph_4_adjacency(khalimsky, extra_border=False):
    """
    Create a 4 adjacency edge-weighted graph from a contour image in the Khalimsky grid.

    :param khalimsky: a 2d array
    :param extra_border: if False the shape of the Khalimsky image  is 2 * shape - 1 and 2 * shape + 1 otherwise, where shape is the shape of the resulting grid graph
    :return: a graph (Concept :class:`~higra.CptGridGraph`) and its edge weights
    """

    graph, embedding, edge_weights = hg.cpp._khalimsky_2_graph_4_adjacency(
        khalimsky, extra_border)

    hg.CptGridGraph.link(graph, embedding.shape())
    hg.set_attribute(graph, "no_border_vertex_out_degree", 4)

    return graph, edge_weights
Ejemplo n.º 13
0
    def test_pickle(self):
        import pickle
        tree = hg.Tree((4, 4, 5, 5, 6, 6, 6))
        lca = hg.LCAFast(tree)
        hg.set_attribute(lca, "test", (1, 2, 3))
        hg.add_tag(lca, "foo")

        data = pickle.dumps(lca)
        lca2 = pickle.loads(data)

        res = lca2.lca((0, 0, 1, 3), (0, 3, 0, 0))
        self.assertTrue(np.all(res == (0, 6, 4, 6)))

        self.assertTrue(
            hg.get_attribute(lca, "test") == hg.get_attribute(lca2, "test"))
        self.assertTrue(lca.test == lca2.test)
        self.assertTrue(hg.has_tag(lca2, "foo"))
Ejemplo n.º 14
0
def __lowest_common_ancestor_preprocess(self):
    """
    Preprocess the tree to obtain a fast constant time :math:`\\mathcal{O}(1)` lowest common ancestor query.
    Once this function has been called on a given tree instance, every following calls to the function
    :func:`~higra.Tree.lowest_common_ancestor` will use this preprocessing.

    :Complexity:

    The preprocessing runs in linearithmic time  :math:`\\mathcal{O}(n\log(n))` with :math:`n` the number of vertices in the tree.

    :return: An object of type :class:`~higra.LCAFast`
    """
    lca_fast = hg.get_attribute(self, "lca_fast")
    if lca_fast is None:
        lca_fast = hg.LCAFast(self)
        hg.set_attribute(self, "lca_fast", lca_fast)
    return lca_fast
Ejemplo n.º 15
0
    def test_pickle(self):
        import pickle
        g = TestUndirectedGraph.test_graph()
        hg.set_attribute(g, "test", (1, 2, 3))
        hg.add_tag(g, "foo")

        data = pickle.dumps(g)
        g2 = pickle.loads(data)

        self.assertTrue(g.num_vertices() == g2.num_vertices())
        gs, gt = g.edge_list()
        g2s, g2t = g2.edge_list()
        self.assertTrue(np.all(gs == g2s))
        self.assertTrue(np.all(gt == g2t))

        self.assertTrue(hg.get_attribute(g, "test") == hg.get_attribute(g2, "test"))
        self.assertTrue(g.test == g2.test)
        self.assertTrue(hg.has_tag(g2, "foo"))
Ejemplo n.º 16
0
    def test_pickle(self):
        import pickle
        tree = hg.Tree((4, 4, 5, 5, 6, 6, 6))
        for lca_t in [hg.LCA_rmq_sparse_table, hg.LCA_rmq_sparse_table_block]:
            with self.subTest(lca_type=lca_t):
                lca = lca_t(tree)
                hg.set_attribute(lca, "test", (1, 2, 3))
                hg.add_tag(lca, "foo")

                data = pickle.dumps(lca)
                lca2 = pickle.loads(data)

                res = lca2.lca((0, 0, 1, 3), (0, 3, 0, 0))
                self.assertTrue(np.all(res == (0, 6, 4, 6)))

                self.assertTrue(hg.get_attribute(lca, "test") == hg.get_attribute(lca2, "test"))
                self.assertTrue(lca.test == lca2.test)
                self.assertTrue(hg.has_tag(lca2, "foo"))
Ejemplo n.º 17
0
    def test_pickle(self):
        import pickle
        t = hg.Tree((5, 5, 6, 6, 6, 7, 7, 7))
        hg.set_attribute(t, "test", (1, 2, 3))
        hg.add_tag(t, "foo")

        data = pickle.dumps(t)
        t2 = pickle.loads(data)

        self.assertTrue(np.all(t.parents() == t2.parents()))

        for v in t.vertices():
            self.assertTrue(np.all(t.children(v) == t2.children(v)))

        self.assertTrue(
            hg.get_attribute(t, "test") == hg.get_attribute(t2, "test"))
        self.assertTrue(t.test == t2.test)
        self.assertTrue(hg.has_tag(t2, "foo"))
Ejemplo n.º 18
0
    def test_consumer(self):
        obj3 = Dummy(3)
        self.assertRaises(Exception, consumer0, obj3)
        self.assertTrue(consumer0(obj3, 1) == 1)
        self.assertTrue(consumer0(obj3, attr0=1) == 1)
        hg.set_attribute(obj3, "attr0", 1)
        self.assertTrue(consumer0(obj3) == 1)
        hg.clear_all_attributes()

        obj4 = Dummy(4)
        self.assertTrue(consumer1(obj4) == 1)
        self.assertTrue(hg.get_attribute(obj4, "attr1") == 1)
        hg.clear_all_attributes()

        obj5 = Dummy(5)
        self.assertTrue(consumer2(obj5) == 1)
        self.assertTrue(hg.get_attribute(obj5, "attr1") == 1)
        hg.clear_all_attributes()
Ejemplo n.º 19
0
def get_4_adjacency_implicit_graph(shape):
    """
    Create an implicit undirected 4 adjacency graph of the given shape (edges are not stored).

    :param shape: a pair (height, width)
    :return: a graph (Concept :class:`~higra.CptGridGraph`)
    """
    shape = hg.normalize_shape(shape)
    if len(shape) != 2:
        raise ValueError("Shape must be a 1d array of size 2.")

    neighbours = np.array(((-1, 0), (0, -1), (0, 1), (1, 0)), dtype=np.int64)
    graph = hg.RegularGraph2d(shape, neighbours)

    hg.CptGridGraph.link(graph, shape)
    hg.set_attribute(graph, "no_border_vertex_out_degree", 4)

    return graph
Ejemplo n.º 20
0
def __lowest_common_ancestor_preprocess(self,
                                        algorithm="sparse_table_block",
                                        block_size=1024,
                                        force_recompute=False):
    """
    Preprocess the tree to obtain a fast constant time :math:`\\mathcal{O}(1)` lowest common ancestor query.
    Once this function has been called on a given tree instance, every following calls to the function
    :func:`~higra.Tree.lowest_common_ancestor` will use this preprocessing. Calling twice this function does nothing
    except if :attr:`force_recompute` is ``True``.

    Two algorithms are available:

    - ``sparse_table`` has a preprocessing time and space complexity in :math:`\\mathcal{O}(n\log(n))` with :math:`n`
      the number of vertices in the tree and performs every query in constant time :math:`\\mathcal{O}(1)`.
    - ``sparse_table_block`` (default) has a linear preprocessing time and space complexity in :math:`\\mathcal{O}(n)`
      and performs queries in average-case constant time :math:`\\mathcal{O}(1)`. With this algorithm the user can specify
      the block size to be used, the general rule of thumb being that larger block size will decrease the pre-processing
      time but increase the query time.

    :param algorithm: specify the algorithm to be used, can be either ``sparse_table`` or ``sparse_table_block``.
    :param block_size: if :attr:`algorithm` is ``sparse_table_block``, specify the block size to be used (default 1024)
    :param force_recompute: if ``False`` (default) calling this function twice won't re-preprocess the tree, even if the
           specified algorithm or algorithm parameter have changed.
    :return: An object of type :class:`~higra.hg.LCA_rmq_sparse_table_block` or :class:`~higra.hg.LCA_rmq_sparse_table`
    """
    lca_fast = hg.get_attribute(self, "lca_fast")
    if lca_fast is None or force_recompute:
        if algorithm == "sparse_table":
            lca_fast = hg.LCA_rmq_sparse_table(self)
        elif algorithm == "sparse_table_block":
            block_size = int(block_size)
            if block_size <= 0:
                raise ValueError("Invalid block size: " + str(block_size))

            lca_fast = hg.LCA_rmq_sparse_table_block(self, block_size)
        else:
            raise ValueError("Unknown LCA algorithm: " + str(algorithm))
        hg.set_attribute(self, "lca_fast", lca_fast)
    return lca_fast
Ejemplo n.º 21
0
    def test_pickle(self):
        import pickle

        tests = ((hg.EmbeddingGrid1d, (3, )), (hg.EmbeddingGrid2d, (3, 2)),
                 (hg.EmbeddingGrid3d, (3, 2, 1)),
                 (hg.EmbeddingGrid4d, (3, 2, 1, 2)), (hg.EmbeddingGrid5d,
                                                      (3, 2, 1, 2, 1)))

        for c, s in tests:
            e = c(s)
            hg.set_attribute(e, "test", (1, 2, 3))
            hg.add_tag(e, "foo")

            data = pickle.dumps(e)
            e2 = pickle.loads(data)

            self.assertTrue(np.all(e.shape() == e2.shape()))

            self.assertTrue(
                hg.get_attribute(e, "test") == hg.get_attribute(e2, "test"))
            self.assertTrue(e.test == e2.test)
            self.assertTrue(hg.has_tag(e2, "foo"))
Ejemplo n.º 22
0
 def link(graph, shape):
     hg.add_tag(graph, CptGridGraph)
     hg.set_attribute(graph, "shape", shape)
Ejemplo n.º 23
0
 def link(caA, ea1):
     hg.add_tag(caA, CptA)
     hg.set_attribute(caA, "ea1", ea1)
Ejemplo n.º 24
0
 def link(rag, pre_graph, vertex_map, edge_map):
     hg.add_tag(rag, CptRegionAdjacencyGraph)
     hg.set_attribute(rag, "vertex_map", vertex_map)
     hg.set_attribute(rag, "edge_map", edge_map)
     hg.set_attribute(rag, "pre_graph", pre_graph)
Ejemplo n.º 25
0
 def link(mst, base_graph, mst_edge_map):
     hg.add_tag(mst, CptMinimumSpanningTree)
     hg.set_attribute(mst, "base_graph", base_graph)
     hg.set_attribute(mst, "mst_edge_map", mst_edge_map)
Ejemplo n.º 26
0
 def link(hierarchy, mst_edge_map, mst):
     hg.add_tag(hierarchy, CptBinaryHierarchy)
     hg.set_attribute(hierarchy, "mst_edge_map", mst_edge_map)
     hg.set_attribute(hierarchy, "mst", mst)
Ejemplo n.º 27
0
 def link(caB, caA, eb2):
     hg.add_tag(caB, CptB)
     hg.set_attribute(caB, "caA", caA)
     hg.set_attribute(caB, "eb2", eb2)
Ejemplo n.º 28
0
 def link(tree, leaf_graph):
     hg.add_tag(tree, CptHierarchy)
     hg.set_attribute(tree, "leaf_graph", leaf_graph)
Ejemplo n.º 29
0
 def link(caC, ec1):
     hg.add_tag(caC, CptC)
     hg.set_attribute(caC, "ec1", ec1)
Ejemplo n.º 30
0
 def test_perimeter_length_partition_tree2(self):
     tree, altitudes = TestAttributes.get_test_tree()
     hg.set_attribute(hg.CptHierarchy.get_leaf_graph(tree), "no_border_vertex_out_degree", None)
     ref_attribute = [2, 3, 2, 3, 4, 3, 2, 3, 2, 3, 3, 5, 3, 3, 4, 5, 0]
     attribute = hg.attribute_perimeter_length(tree, no_cache=True)
     self.assertTrue(np.allclose(ref_attribute, attribute))