<jupyter_start><jupyter_text>Find the EchoIf we have a two signals with one being a fainter, delayed, noisy version of the other (let's call it the echo)we can compute the delay between the two.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
import scipy.signal

plt.rcParams['figure.facecolor'] = '.95'<jupyter_output><empty_output><jupyter_text>Let's create the signal and its echo:<jupyter_code>N = 100
xs = np.arange(N)

a = 42
signal = a*np.sin(np.pi/10*xs) + xs

echo_delay = 7
echo_strength = 0.3 # attenuation

echo = np.zeros_like(signal)
echo[echo_delay:] = signal[:-echo_delay]*echo_strength<jupyter_output><empty_output><jupyter_text>Let's see what it looks like.<jupyter_code>fig, (ax_sig, ax_echo) = plt.subplots(nrows=2, sharex=True, sharey=True)
plt.suptitle('Signal and Echo')
ax_sig.plot(xs, signal, label='signal')
ax_echo.plot(xs, echo, '--', label='echo')
ax_sig.legend()
ax_echo.legend()<jupyter_output><empty_output><jupyter_text>Let's see how the it looks when we convolve and cross-correlate the signal and echo:<jupyter_code>convolved = scipy.signal.fftconvolve(echo, signal, mode='same')
crosscorrelated = scipy.signal.correlate(echo, signal, mode='same')

plt.suptitle('Convolution and cross-correlation')
plt.plot(convolved, ':', label='Convolved: signal * echo')
plt.plot(crosscorrelated, ':', label='Cross-correlated: signal * echo')
plt.legend()<jupyter_output><empty_output><jupyter_text>We can get the lag (delay) using the cross-correlated signal and echo.It is the index with the highest value.<jupyter_code># Compute the lag directly
delays = np.linspace(-int(N/2), int(N/2)-1, N)
cc_argmax = np.argmax(crosscorrelated)
lag = delays[cc_argmax]
print(f'lag = {lag}')<jupyter_output><empty_output><jupyter_text>Matplotlib also comes with a built-in plotting function to do the same.It is probably named after the `xcorr` function in Matlab.<jupyter_code># We can also get the lag from plt.xcorr
(lags, c, line, b) = plt.xcorr(echo, signal)
lag = lags[np.argmax(c)]
print(f'lag = {lag}')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13152804642166344, 'fraction_numerical': 0.007736943907156673, 'mean_word_length': 6.720149253731344, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '13872', 'license': 'MIT', 'n_tokens_mistral': 793, 'n_tokens_neox': 750, 'n_words': 189, 'path': 'find_echo.ipynb', 'repo_name': 'mjul/scipy-lab', 'size': '2068'}