信号がどの値の間で遷移しているかが分かっていて、ノイズが大きすぎない場合は、30% のすべての交差と 70% のすべての交差の間の時間差を単純に計算し、最小のものを維持することができます。
import numpy as np
import matplotlib.pyplot as plt
s100, s0 = 5, 0
signal = np.concatenate((np.ones((25,)) * s100,
s100 + (np.random.rand(25) - 0.5) * (s100-s0),
np.linspace(s100, s0, 25),
s0 + (np.random.rand(25) - 0.5) * (s100-s0),
np.ones((25,)) * s0))
# Interpolate to find crossings with 30% and 70% of signal
# The general linear interpolation formula between (x0, y0) and (x1, y1) is:
# y = y0 + (x-x0) * (y1-y0) / (x1-x0)
# to find the x at which the crossing with y happens:
# x = x0 + (y-y0) * (x1-x0) / (y1-y0)
# Because we are using indices as time, x1-x0 == 1, and if the crossing
# happens within the interval, then 0 <= x <= 1.
# The following code is just a vectorized version of the above
delta_s = np.diff(signal)
t30 = (s0 + (s100-s0)*.3 - signal[:-1]) / delta_s
idx30 = np.where((t30 > 0) & (t30 < 1))[0]
t30 = idx30 + t30[idx30]
t70 = (s0 + (s100-s0)*.7 - signal[:-1]) / delta_s
idx70 = np.where((t70 > 0) & (t70 < 1))[0]
t70 = idx70 + t70[idx70]
# compute all possible transition times, keep the smallest
idx = np.unravel_index(np.argmin(t30[:, None] - t70),
(len(t30), len(t70),))
print t30[idx[0]] - t70[idx[1]]
# 9.6
plt. plot(signal)
plt.plot(t30, [s0 + (s100-s0)*.3]*len(t30), 'go')
plt.plot(t30[idx[0]], [s0 + (s100-s0)*.3], 'o', mec='g', mfc='None', ms=10)
plt.plot(t70, [s0 + (s100-s0)*.7]*len(t70), 'ro')
plt.plot(t70[idx[1]], [s0 + (s100-s0)*.7], 'o', mec='r', mfc='None', ms=10 )
plt.show()