Pattern Matching and Alignment

In this notebook, we show how to do pattern matching and alignment using secbench primitives.

import importlib

import numpy as np
import matplotlib.pyplot as plt

# NOTE: tune the figure size as needed for better visualization in the notebook
plt.rcParams["figure.figsize"] = (14, 6)
from secbench.processing.helpers import qplot
from secbench.processing.signal import match_correlation, match_euclidean, phase_correlation

Input Generation

We start by generating a simple pattern:

pattern_width = 300

xs = np.linspace(-1, 3, pattern_width)
pattern = 2. * (np.sinc(xs**2) - np.sinc(xs - 4) + np.sinc(5 * xs) - 1)
pattern = pattern.astype(np.float32)
plt.plot(pattern)
plt.title("Reference pattern")
plt.show()
../_images/cdcd430623d05ac5a9134bc57805d692dbf43828da4c2c2a7a0383bc30589fa4.png

Then, we generate a trace and insert the pattern into it.

samples = 5000

offset = 300 # np.random.randint(pattern_width, samples - pattern_width)
p_start, p_end = offset, offset + pattern_width

data = np.random.normal(size=samples).astype(np.float32)
data[p_start:p_end] += pattern
print(f"offest is {offset}")

plt.plot(data)
plt.axvline(p_start, color="r")
plt.axvline(p_end, color="r")
plt.title("noisy trace with a pattern")
plt.show()
offest is 300
../_images/36011cd4910a895dc5a8db82392bae95479b292927f643b0fd391e1a79f1684f.png

Pattern Matching

Now, we run the different matchers available:

matchers = [
    ("correlation", match_correlation, "max"),
    ("Eucliean distance", match_euclidean, "min"),
    ("Phase correlation", phase_correlation, "max")]

solutions = []
for label, matcher, order in matchers:
    fig, ax1 = plt.subplots()
    ax1.set_ylabel("metric")
    score = matcher(data, pattern, dtype=np.float32)
    sol = np.argmin(score) if order == "min" else np.argmax(score)
    solutions.append(sol)
    ax1.plot(score, color="red")
    ax1.axvline(sol, color="black", linestyle="--")

    ax2 = ax1.twinx()
    ax2.plot(data, alpha=0.3, color="green")
    ax2.set_ylabel("sample value")
    plt.title(f"Pattern matching with {label}")
    plt.show()

for (label, _, _), sol in zip(matchers, solutions):
    print(f"offset found by {label}: {sol}")
../_images/8dad32f46025315c7aec5ee42da28608b3e67ccccaa7e581ce554f5ec43b1792.png ../_images/1cef3d0a29c9b3d54ca373840a10008b39d85c1ca9dbd3dca273fd77ba94a131.png ../_images/7d181c789e2b15d09b45cc3dce7b79e9b069f195aa9e6c0d5c64be3bacf30492.png
offset found by correlation: 300
offset found by Eucliean distance: 300
offset found by Phase correlation: 300

Alignment

Traces alignement simply consists of finding the pattern location in each trace and shifting them accordingly.

This section shows a basic example.

We first generate more traces using the same technique as in the previous section.

samples = 5000

data = np.zeros((50, samples), dtype=np.float32)

for i in range(data.shape[0]):
    offset = np.random.randint(1000, 1500)
    p_start, p_end = offset, offset + pattern_width
    data[i] = np.random.normal(size=samples).astype(np.float32)
    data[i, p_start:p_end] += pattern
qplot(data, plot_mean=True)
plt.title("Unaligned traces overlaid")
plt.show()
../_images/b4ea66b880566a8c2bc1f35afcb3df43829129467c9f6e0f2229feaf7a93446c.png

We now run the alignment.

matchers = [
    ("correlation", match_correlation, "max"),
    ("eucliean distance", match_euclidean, "min"),
    ("phase correlation", phase_correlation, "max")]

for label, matcher, order in matchers:
    
    fig, ax1 = plt.subplots()
    ax1.set_ylabel("metric")
    score = matcher(data, pattern)
    sol = np.argmin(score, axis=1) if order == "min" else np.argmax(score, axis=1)

    d_aligned = np.copy(data)
    for i, sh in enumerate(sol):
        d_aligned[i] = np.roll(d_aligned[i], -sh)

    ax1.plot(np.mean(d_aligned, axis=0))
    plt.title(f"Alignment with {label}")
    plt.show()
../_images/7700c9606f925d06ae83782a856268284fe5ce7c62ce17550f1fa5c948bd905f.png ../_images/47398f16774f63847162b97f4cbf638120e0f1db688f5b3b3ccd1d36f1a357ac.png ../_images/66891f24af282b000fe61c233ace00d5fa724ce7c8064748eb8c730b026a0dc0.png