Source code for openalea.phenomenal.tracking.alignment_postprocessing
"""
Functions used in the following post-processing steps after the alignment of
sequences of ligulated leaves :
- Remove abnormal columns in the alignment matrix (i.e. ranks corresponding to
artefacts, not to real leaves).
(detect_abnormal_ranks)
- Backwards tracking of each leaf in its growth phase until its emergence.
(leaf_polylines_distance)
"""
import numpy as np
from openalea.phenomenal.tracking.polyline_utils import (
polyline_quantile_coordinate,
polyline_length,
)
[docs]
def detect_abnormal_ranks(alignment_matrix):
"""
Specific to plant alignment.
Detect abnormal columns in 'alignment_matrix' object resulting from multi
alignment based on the following criteria:
- A column is abnormal if it contains 2 times less aligned vectors in
average (value != -1 in 'alignment_matrix') than the surrounding columns.
- first and last columns can't be abnormal
Parameters
----------
alignment_matrix : 2D array
result of multi_alignment() function
Returns
-------
"""
alignment_matrix = np.array(alignment_matrix)
counts = [
len([k for k in alignment_matrix[:, i] if k != -1])
for i in range(alignment_matrix.shape[1])
]
abnormal_ranks = []
for i, value in enumerate(counts):
if 0 < i < len(counts) - 1 and value < 0.5 * np.mean(
[counts[i - 1], counts[i + 1]]
):
abnormal_ranks.append(i)
return abnormal_ranks
[docs]
def leaf_polylines_distance(polyline_ref, polyline_candidate, n=20):
"""
Computes the distance between two leaf polylines.
Parameters
----------
polyline_ref : array
polyline_candidate : array
n : int
Returns
-------
"""
# computing distance
dist = 0
for q in np.linspace(0, 1, n):
pos1 = polyline_quantile_coordinate(polyline_ref, q)
pos2 = polyline_quantile_coordinate(polyline_candidate, q)
dist += np.sqrt(np.sum((pos1 - pos2) ** 2))
# scale standardization
dist_rescaled = dist / np.max((polyline_length(polyline_ref), 1e-6))
return dist_rescaled