Ejemplo n.º 1
0
 def test_vertex_coordinates(self):
     g = hg.get_4_adjacency_graph((2, 3))
     ref = np.asarray((((0, 0), (0, 1), (0, 2)), ((1, 0), (1, 1), (1, 2))))
     res = hg.attribute_vertex_coordinates(g)
     self.assertTrue(np.allclose(ref, res))
Ejemplo n.º 2
0
def attribute_moment_of_inertia(tree, leaf_graph):
    """
    Moment of inertia (first Hu moment) of each node of the given tree.
    This function works only if :attr:`leaf_graph` is a 2D grid graph.
    The moment of inertia is a translation, scale and rotation invariant characterization of the shape of the nodes.

    Given a node :math:`X` of :attr:`tree`, the raw moments :math:`M_{ij}` are defined as:

    .. math::

        M_{ij} = \sum_{x}\sum_{y} x^i y^j

    where :math:`(x,y)` are the coordinates of every vertex in :math:`X`.
    Then, the centroid :math:`\{\overline{x},\overline{y}\}` of :math:`X` is given by

    .. math::

         \overline{x} = \\frac{M_{10}}{M_{00}} \\textrm{ and  } \overline{y} = \\frac{M_{01}}{M_{00}}

    Some central moments of :math:`X` are then:

    - :math:`\mu_{00} = M_{00}`
    - :math:`\mu_{20} = M_{20} - \overline{x} \\times M_{10}`
    - :math:`\mu_{02} = M_{02} - \overline{y} \\times M_{01}`

    The moment of inertia :math:`I_1` of :math:`X` if finally defined as

    .. math::

        I_1 = \eta_{20} + \eta_{02}
        
    where :math:`\eta_{ij}` are given by:
    
        :math:`\eta_{ij} = \\frac{\mu_{ij}}{\mu_{00}^{1+\\frac{i+j}{2}}}`

    :param tree: input tree (Concept :class:`~higra.CptHierarchy`)
    :param leaf_graph: graph on the leaves of the input tree (deduced from :class:`~higra.CptHierarchy` on `tree`)
    :return: a 1d array
    """

    if (not hg.CptGridGraph.validate(leaf_graph)) or (len(
            hg.CptGridGraph.get_shape(leaf_graph)) != 2):
        raise ValueError("Parameter 'leaf_graph' must be a 2D grid graph.")

    coordinates = hg.attribute_vertex_coordinates(leaf_graph)
    coordinates = np.reshape(
        coordinates,
        (coordinates.shape[0] * coordinates.shape[1], coordinates.shape[2]))

    M_00_leaves = np.ones((tree.num_leaves())).astype(dtype=np.float64)
    x_leaves = coordinates[:, 0].astype(dtype=np.float64)
    y_leaves = coordinates[:, 1].astype(dtype=np.float64)

    M_10_leaves = x_leaves * M_00_leaves
    M_01_leaves = y_leaves * M_00_leaves
    M_20_leaves = (x_leaves**2) * M_00_leaves
    M_02_leaves = (y_leaves**2) * M_00_leaves

    M_00 = hg.accumulate_sequential(tree, M_00_leaves, hg.Accumulators.sum)
    M_01 = hg.accumulate_sequential(tree, M_01_leaves, hg.Accumulators.sum)
    M_10 = hg.accumulate_sequential(tree, M_10_leaves, hg.Accumulators.sum)
    M_02 = hg.accumulate_sequential(tree, M_02_leaves, hg.Accumulators.sum)
    M_20 = hg.accumulate_sequential(tree, M_20_leaves, hg.Accumulators.sum)

    _x = M_10 / M_00
    _y = M_01 / M_00
    miu_20 = M_20 - _x * M_10
    miu_02 = M_02 - _y * M_01
    I_1 = (miu_20 + miu_02) / (M_00**2)

    return I_1