1

As title, I am working on time-series alignment, and a visualization of the alignment result is desired.

To this end, I want to draw lines connecting "anchor points" generated by the alignment algorithm.

np.random.seed(5)
x = np.random.rand(10)      # time-series 1
y = np.random.rand(20)      # time-series 2
ap = np.array(([0, 4,  9],  # the anchor points
               [0, 9, 19]))

fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.plot(x, 'r')
ax2.plot(y, 'g')

the anchor points ap in the example specify the one-to-one "mapping" between the indices of two time series x and y, i.e., x[0] is corresponding to y[0]; x[4] to y[9]; and x[9] to y[19]. The goal is to draw lines between two separate plot to show the result of the alignment.

Francis
  • 6,416
  • 5
  • 24
  • 32

2 Answers2

1

To connect two subplots in matplotlib you may use a ConnectionPatch.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

np.random.seed(5)
x = np.random.rand(21)      # time-series 1
y = np.random.rand(21)      # time-series 2
ap = np.array(([0, 5, 10],  # the anchor points
               [0,10, 20]))

fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.plot(x, 'r')
ax2.plot(y, 'g')

ls = ["-","--"]
c = ["gold", "blue"]

for i, row in enumerate(ap):
    for j, ind in enumerate(row):
        px = (ind, x[ind])
        py = (ind, y[ind])
        con = ConnectionPatch(py,px, coordsA="data", coordsB="data",
                      axesA=ax2, axesB=ax1, linestyle=ls[i], color=c[i])
        ax2.add_artist(con)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
0

Thanks to @ImportanceOfBeingErnest, I identified the typo in the OP and achieved connecting indices between two series of different length:

np.random.seed(5)
x = np.random.rand(10)
y = np.random.rand(20)
ap = np.array(([0, 4, 9],
               [0,9, 19]))

fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212, sharex=ax1)
ax1.plot(x, 'r')
ax2.plot(y, 'g')

plt.setp(ax1.get_xticklabels(), visible=False)

for j in ap.T:

    ax1.axvline(x=j[0], linestyle='--', color='k')
    ax2.axvline(x=j[1], linestyle='--', color='k')

    x_ind = (j[0], ax1.get_ylim()[0])
    y_ind = (j[1], ax2.get_ylim()[1])

    con = ConnectionPatch(y_ind, x_ind, coordsA="data", coordsB="data",
                          axesA=ax2, axesB=ax1, linewidth='1.5')

    ax2.add_artist(con)

enter image description here

I know it is off the topic, but how to further truncate the blank part in order to make the range of x-axis fit the signal length, while maintain the actual ratio of the length of the two signals? Though sharex=ax1 shows the ratio of signal length, the blank part on the right of the top figure is annoying.

Francis
  • 6,416
  • 5
  • 24
  • 32