Ejemplo n.º 1
0
    def test_tree_accumulator(self):
        tree = TestTreeAccumulators.get_tree()
        input_array = np.asarray((1, 1, 1, 1, 1, 1, 1, 1))

        res1 = hg.accumulate_parallel(tree, input_array, hg.Accumulators.sum)
        ref1 = np.asarray((0, 0, 0, 0, 0, 2, 3, 2))
        self.assertTrue(np.allclose(ref1, res1))

        leaf_data = np.asarray((1, 1, 1, 1, 1))
        res2 = hg.accumulate_sequential(tree, leaf_data, hg.Accumulators.sum)
        ref2 = np.asarray((1, 1, 1, 1, 1, 2, 3, 5))
        self.assertTrue(np.allclose(ref2, res2))

        res3 = hg.accumulate_and_add_sequential(tree, input_array, leaf_data, hg.Accumulators.max)
        ref3 = np.asarray((1, 1, 1, 1, 1, 2, 2, 3))
        self.assertTrue(np.allclose(ref3, res3))

        input_array = np.asarray((1, 2, 1, 2, 1, 1, 4, 5))
        res4 = hg.accumulate_and_max_sequential(tree, input_array, leaf_data, hg.Accumulators.sum)
        ref4 = np.asarray((1, 1, 1, 1, 1, 2, 4, 6))
        self.assertTrue(np.allclose(ref4, res4))

        input_array = np.asarray((1, 2, 1, 2, 1, 2, 3, 1))
        res5 = hg.accumulate_and_multiply_sequential(tree, input_array, leaf_data, hg.Accumulators.sum)
        ref5 = np.asarray((1, 1, 1, 1, 1, 4, 9, 13))
        self.assertTrue(np.allclose(ref5, res5))

        input_array = np.asarray((1, 2, 1, 2, 1, 4, 2, 10))
        res6 = hg.accumulate_and_min_sequential(tree, input_array, leaf_data, hg.Accumulators.sum)
        ref6 = np.asarray((1, 1, 1, 1, 1, 2, 2, 4))
        self.assertTrue(np.allclose(ref6, res6))
Ejemplo n.º 2
0
    def num_parents(bpt_tree, altitudes):
        # construct quasi flat zone hierarchy from input bpt
        tree, node_map = hg.simplify_tree(
            bpt_tree, altitudes == altitudes[bpt_tree.parents()])

        # determine inner nodes of the min tree, i.e. nodes of qfz having at least one node that is not a leaf
        num_children = tree.num_children(np.arange(tree.num_vertices()))
        num_children_leaf = np.zeros((tree.num_vertices(), ), dtype=np.int64)
        np.add.at(num_children_leaf, tree.parents()[:tree.num_leaves()], 1)
        inner_nodes = num_children != num_children_leaf

        # go back into bpt space
        inner_nodes_bpt = np.zeros((bpt_tree.num_vertices(), ), dtype=np.int64)
        inner_nodes_bpt[node_map] = inner_nodes
        inner_nodes = inner_nodes_bpt

        # count number of min tree inner nodes in the subtree rooted in the given node
        res = hg.accumulate_and_add_sequential(bpt_tree, inner_nodes,
                                               inner_nodes[:tree.num_leaves()],
                                               hg.Accumulators.sum)

        # add 1 to avoid having a zero measure in a minima
        res[bpt_tree.num_leaves():] = res[bpt_tree.num_leaves():] + 1

        return res
Ejemplo n.º 3
0
    def test_tree_accumulatorVec(self):
        tree = TestTreeAccumulators.get_tree()
        input_array = np.asarray(((1, 0),
                                  (1, 1),
                                  (1, 2),
                                  (1, 3),
                                  (1, 4),
                                  (1, 5),
                                  (1, 6),
                                  (1, 7)))

        res1 = hg.accumulate_parallel(tree, input_array, hg.Accumulators.sum)
        ref1 = np.asarray(((0, 0),
                           (0, 0),
                           (0, 0),
                           (0, 0),
                           (0, 0),
                           (2, 1),
                           (3, 9),
                           (2, 11)))
        self.assertTrue(np.allclose(ref1, res1))

        leaf_data = np.asarray(((1, 0),
                                (1, 1),
                                (1, 2),
                                (1, 3),
                                (1, 4)))
        res2 = hg.accumulate_sequential(tree, leaf_data, hg.Accumulators.sum)
        ref2 = np.asarray(((1, 0),
                           (1, 1),
                           (1, 2),
                           (1, 3),
                           (1, 4),
                           (2, 1),
                           (3, 9),
                           (5, 10)))
        self.assertTrue(np.allclose(ref2, res2))

        res3 = hg.accumulate_and_add_sequential(tree, input_array, leaf_data, hg.Accumulators.sum)
        ref3 = np.asarray(((1, 0),
                           (1, 1),
                           (1, 2),
                           (1, 3),
                           (1, 4),
                           (3, 6),
                           (4, 15),
                           (8, 28)))
        self.assertTrue(np.allclose(ref3, res3))
Ejemplo n.º 4
0
def attribute_topological_height(tree):
    """
    Given a node :math:`n` of :attr:`tree`, the topological height of :math:`n` is the number of edges on the longest
    path from the node :math:`n` to a leaf of :attr:`tree`.

    The topological height of the leaves is equal to 0.

    :param tree: Input tree
    :return: a 1d array
    """

    res = hg.accumulate_and_add_sequential(
        tree, np.ones(tree.num_vertices(), dtype=np.int64),
        np.zeros(tree.num_leaves(), dtype=np.int64), hg.Accumulators.max)

    return res
Ejemplo n.º 5
0
def attribute_perimeter_length_partition_tree(tree, vertex_perimeter, frontier_length, leaf_graph=None):
    """
    Length of the perimeter of each node of the given partition tree.

    **Provider name**: "perimeter_length_partition_tree"

    :param tree: input tree (Concept :class:`~higra.CptHierarchy`)
    :param vertex_perimeter: perimeter length of each vertex of the leaf graph (provided by :func:`~higra.attribute_vertex_perimeter` on `leaf_graph`)
    :param frontier_length: length of common contour between merging regions (provided by :func:`~higra.attribute_frontier_length` on `tree`)
    :param leaf_graph: (deduced from :class:`~higra.CptHierarchy`)
    :return: a 1d array
    """
    assert (tree.category() == hg.TreeCategory.PartitionTree)
    if leaf_graph is not None:
        vertex_perimeter = hg.linearize_vertex_weights(vertex_perimeter, leaf_graph)

    return hg.accumulate_and_add_sequential(tree, -2 * frontier_length, vertex_perimeter, hg.Accumulators.sum)
Ejemplo n.º 6
0
def attribute_contour_length(tree,
                             vertex_perimeter=None,
                             edge_length=None,
                             leaf_graph=None):
    """
    Length of the contour (perimeter) of each node of the given tree.

    :param tree: input tree (Concept :class:`~higra.CptHierarchy`)
    :param vertex_perimeter: perimeter of each vertex of the leaf graph (provided by :func:`~higra.attribute_vertex_perimeter` on `leaf_graph`)
    :param edge_length: length of each edge of the leaf graph (provided by :func:`~higra.attribute_edge_length` on `leaf_graph`)
    :param leaf_graph: (deduced from :class:`~higra.CptHierarchy`)
    :return: a 1d array
    """

    if vertex_perimeter is None:
        vertex_perimeter = hg.attribute_vertex_perimeter(leaf_graph)

    if edge_length is None:
        edge_length = hg.attribute_edge_length(leaf_graph)

    if leaf_graph is not None:
        vertex_perimeter = hg.linearize_vertex_weights(vertex_perimeter,
                                                       leaf_graph)

    frontier_length = hg.attribute_frontier_length(tree, edge_length,
                                                   leaf_graph)
    perimeter = hg.accumulate_and_add_sequential(tree, -2 * frontier_length,
                                                 vertex_perimeter,
                                                 hg.Accumulators.sum)

    # hg.cpp._attribute_contour_length_component_tree is more efficient than the partition tree
    # algorithm but it does not work for tree of shapes left in original space (the problem is that
    # two children of a node may become adjacent when the interpolated pixels are removed).

    # if tree.category() == hg.TreeCategory.PartitionTree:
    #     frontier_length = hg.attribute_frontier_length(tree, edge_length, leaf_graph)
    #     perimeter = hg.accumulate_and_add_sequential(tree, -2 * frontier_length, vertex_perimeter,
    #                                                  hg.Accumulators.sum)
    # elif tree.category() == hg.TreeCategory.ComponentTree:
    #     perimeter = hg.cpp._attribute_contour_length_component_tree(tree, leaf_graph, vertex_perimeter,
    #                                                                 edge_length)

    return perimeter
Ejemplo n.º 7
0
def attribute_volume(tree, altitudes, area):
    """
    Volume of each node the given tree.
    The volume :math:`V(n)` of a node :math:`n` is defined recursively as:

    .. math::

        V(n) = area(n) * | altitude(n) - altitude(parent(n)) | +  \sum_{c \in children(n)} V(c)

    **Provider name**: "volume"

    :param tree: input tree
    :param altitudes: node altitudes of the input tree
    :param area: area of the nodes of the input hierarchy (provided by :func:`~higra.attribute_area` on `tree`)
    :return: a 1d array
    """
    height = np.abs(altitudes[tree.parents()] - altitudes)
    height = height * area
    volume_leaves = height[:tree.num_leaves()]
    return hg.accumulate_and_add_sequential(tree, height, volume_leaves, hg.Accumulators.sum)