-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question on whether it is possible to optimize many Recurrence Plots production #88
Comments
Yes, sure! You just have to compute the images without using a threshold ( Here is an example: import numpy as np
from pyts.image import RecurrencePlot
# Create a toy data set
rng = np.random.RandomState(42)
n_samples, n_timestamps = 200, 48
X = rng.randn(n_samples, n_timestamps)
# Compute the recurrence plots with no threshold
X_rp = RecurrencePlot(threshold=None).transform(X)
# Compute the thresholds (each percentile here)
thresholds = np.percentile(
np.reshape(X_rp, (n_samples, -1)),
np.arange(1, 100), axis=1
)
X_rp_thresholds = np.empty((thresholds.size, *X_rp.shape))
# Binarize the recurrence plots for each threshold
for i, thresh in enumerate(thresholds):
X_rp_thresholds[i] = X_rp <= thresh[:, None, None] You can show all the images on one figure like this: import matplotlib.pyplot as plt
# Choose the index of the time series
idx = 10
# Plot the recurrence plot for each threshold
plt.figure(figsize=(5, 20))
for i in range(thresholds.shape[0]):
plt.subplot(20, 5, i + 1)
plt.imshow(X_rp_thresholds[i, idx], cmap='binary', origin='lower')
plt.axis('off')
plt.show() To make a video, here are a few ressources (found with a quick research):
But maybe you can do the video yourself without python by saving each image? |
Ah, this is really cool, much simpler than I expected. I don't really need help with making a video, I have already made a tiny library using opencv for that. Thanks so much for your feedback |
This seems to be a very heavy operation to perform. The following line in your code
seems to require 68Gb of space. |
Wait, I'm confused. Why does |
The library is designed from a machine learning point of view, so it expects a data set, that is a set of time series. Moreover, it is mostly designed to deal with univariate time series, although it can also handle multivariate time series. If I guess it right, you only have one time series but a multivariate one? So you have a 2D-array with the first axis being the dimension (channel) and the second axis being time? And you want to compute only one recurrence plot for all the dimensions (instead of one for each dimension independently)? Here is a detailed example: import numpy as np
from numpy.lib.stride_tricks import as_strided
from pyts.image import RecurrencePlot
from scipy.spatial.distance import squareform
# Create a multivariate time series with 12 dimensions and 480 timepoints
rng = np.random.RandomState(42)
n_dimensions, n_timestamps = 12, 480
x = rng.randn(n_dimensions, n_timestamps)
# Define a function that will compute all the trajectories and save them in a 3D-array
def compute_trajectories(x, trajectory_size, time_delay):
n_dimensions, n_timestamps = x.shape
shape_new = (n_dimensions,
n_timestamps - (trajectory_size - 1) * time_delay,
trajectory_size)
s0, s1 = x.strides
strides_new = (s0, s1, time_delay * s1)
return as_strided(x, shape=shape_new, strides=strides_new)
# Compute all the trajectories
# The number of trajectories is equal to n_timestamps - (trajectory_size - 1) * time_delay
trajectory_size = 4
time_delay = 2
x_traj = compute_trajectories(x, trajectory_size, time_delay)
# Compute the distance between each trajectory using the Euclidean distance
# This is the unthresholded recurrence plot
# We sum over axis 0 (dimensions) and axis 3 (trajectory_size)
# The output is a 2D-array with shape (n_trajectories, n_trajectories)
x_dist = np.sqrt(
np.sum((x_traj[:, None, :, :] - x_traj[:, :, None, :]) ** 2,
axis=(0, 3))
)
# Compute the thresholds (each percentile here)
thresholds = np.percentile(x_dist.ravel(), np.arange(1, 100))
# Note that the matrix is symmetric and that the diagonale is full of zeros
# because the distance between two identical trajectories is null.
# You can also compute the thresholds using only the upper (or lower) triangular entries
thresholds_alt = np.percentile(squareform(x_dist), np.arange(1, 100))
# Binarize the recurrence plots for each threshold
x_rp_thresholds = np.empty((thresholds_alt.size, *x_dist.shape))
for i, thresh in enumerate(thresholds):
x_rp_thresholds[i] = x_dist <= thresh The documentation explains how trajectories are computed, if it's not clear. In your case, I guess that you assume |
Ah yes, I just did more or less what you wrote, works very nicely. I can provide an example with interactive jupyter plot, where I can slide over percentile with a slider, very convenient. Two further questions, if I may:
|
Hope this helps you a bit. |
Thanks a lot for your suggestions! This is all extremely helpful to me! I will go through the publications you suggest. The goal really is to build a toolbox for neuroscience applications within our research group. I really liked the recurrence plots because they enable to see by eye what is going on to get intuition. The real problem is that there is a very complicated, possibly chaotic system at hand, and while there are many deep learning methods proposed to decode what is going on, the only real way to debug and understand HOW the neuronal populations encode data is to project the multivariate phase-space onto some simple metrics to filter out possible hypotheses |
So recurrence plot
pyts.image.RecurrencePlot
works really nicely, but can be a bit slow. I want to write a function that would make a movie forthreshold='point'
andpercentage
in range 0 to 100. I can do it trivially by repeating the plot independently 100 times, but I presume that (theoretically) some part of the work can be re-used if percentage is changed but data stays the same. Can this be done?The text was updated successfully, but these errors were encountered: