Landmark shift#

This example shows how to shift functional data objects to align its samples with a particular reference point.

# Author: Pablo Marcos Manchón
# License: MIT

# sphinx_gallery_thumbnail_number = 2

We will use an example dataset synthetically generated by make_multimodal_samples(), which in this case will be used to generate gaussian-like samples with a mode near to 0. Each sample will be shifted to align their modes to a reference point using the function landmark_shift_registration().

import matplotlib.pyplot as plt

from skfda.datasets import make_multimodal_samples

fd = make_multimodal_samples(random_state=1)
fd.extrapolation = "bounds"  # See extrapolation for a detailed explanation.

fd.plot()
plt.show()
plot landmark shift

A landmark or a feature of a curve is some characteristic that one can associate with a specific argument value t. These are typically maxima, minima, or zero crossings of curves, and may be identified at the level of some derivatives as well as at the level of the curves themselves[1].

For alignment we need to know in advance the location of the landmark of each of the samples, in our case it will correspond to the maxima of each sample. Because our dataset has been generated synthetically we can obtain the value of the landmarks using the function make_multimodal_landmarks(), which is used by make_multimodal_samples() to set the location of the modes.

In general it will be necessary to use numerical or other methods to determine the location of the landmarks.

import numpy as np

from skfda.datasets import make_multimodal_landmarks

landmarks = make_multimodal_landmarks(random_state=1).squeeze()

fig, ax = plt.subplots()
ax.scatter(landmarks, np.repeat(1, fd.n_samples))
fd.plot(fig=fig)
plt.show()
plot landmark shift

Location of the landmarks:

print(landmarks)
[ 0.36321467 -0.13679289 -0.11810279 -0.23992308  0.19351103 -0.5146397
  0.39015177 -0.17021104  0.07133931 -0.05576091  0.32693727 -0.46066147
 -0.07209468 -0.08587716  0.25351855]

The following figure shows the result of shifting the curves to align their landmarks at 0.

from skfda.preprocessing.registration import landmark_shift_registration

fd_registered = landmark_shift_registration(
    fd,
    landmarks,
    location=0,
)

fig = fd_registered.plot()
fig.axes[0].scatter(0, 1)
plt.show()
plot landmark shift

In many circumstances it is possible that we could not apply extrapolation, in these cases it is possible to restrict the domain to avoid evaluating points outside where our curves are defined.

If the location of the new reference point is not specified it is choosen the point that minimizes the maximum amount of shift.

# Curves aligned restricting the domain
fd_restricted = landmark_shift_registration(
    fd,
    landmarks,
    restrict_domain=True,
)

# Curves aligned to default point without restrict domain
fd_extrapolated = landmark_shift_registration(
    fd,
    landmarks,
)


fig = fd_extrapolated.plot(linestyle="dashed", label="Extrapolated samples")
fd_restricted.plot(fig=fig, label="Restricted samples")
plt.show()
plot landmark shift

The previous method is also applicable for multidimensional objects, without limitation of the domain or image dimension. As an example we are going to create a datset with surfaces, in a similar way to the previous case.

fd = make_multimodal_samples(
    n_samples=3,
    points_per_dim=30,
    dim_domain=2,
    random_state=1,
)

fd.plot()
plt.show()
plot landmark shift

In this case the landmarks will be defined by tuples with 2 coordinates.

landmarks = make_multimodal_landmarks(
    n_samples=3,
    dim_domain=2,
    random_state=1,
).squeeze()
print(landmarks)
[[ 0.36321467 -0.13679289]
 [-0.11810279 -0.23992308]
 [ 0.19351103 -0.5146397 ]]

As in the previous case, we can align the curves to a specific point, or by default will be chosen the point that minimizes the maximum amount of displacement.

fd_registered = landmark_shift_registration(
    fd,
    landmarks,
)

fd_registered.plot()
plt.show()
plot landmark shift

Total running time of the script: (0 minutes 0.492 seconds)

Gallery generated by Sphinx-Gallery