diff --git a/notebooks/how_to_find_1d_motifs.ipynb b/notebooks/how_to_find_1d_motifs.ipynb new file mode 100644 index 0000000..e6994fa --- /dev/null +++ b/notebooks/how_to_find_1d_motifs.ipynb @@ -0,0 +1,89 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "50db9d0d", + "metadata": {}, + "source": [ + "# How do I find the most similar pair of time series sub-sequences (motifs)?\n", + "\n", + "*Reproducing Slide 3 from Eamonn Keogh's \"100 Time Series Data Mining Questions (with Answers)\" using STUMPY.*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c544e39", + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'numpy'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mModuleNotFoundError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m numpy \u001b[38;5;28;01mas\u001b[39;00m np\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m stumpy\n\u001b[32m 3\u001b[39m \n\u001b[32m 4\u001b[39m \u001b[38;5;66;03m# 1. Generate or load a 1D time series (array-like, float64)\u001b[39;00m\n", + "\u001b[31mModuleNotFoundError\u001b[39m: No module named 'numpy'" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import stumpy\n", + "\n", + "# 1. Load exact Slide 3 dataset (Sony AIBO Robot Dog Accelerometer & Carpet Query)\n", + "T = np.loadtxt(\"https://raw.githubusercontent.com/TDAmeritrade/stumpy/main/docs/Tutorial_Pattern_Matching_steam_gen.txt\")\n", + "Q = np.loadtxt(\"https://raw.githubusercontent.com/TDAmeritrade/stumpy/main/docs/Tutorial_Pattern_Matching_carpet_query.txt\")\n", + "\n", + "# 2. Find closest query match in 1 line using MASS\n", + "distance_profile = stumpy.mass(Q, T)\n", + "idx = np.argmin(distance_profile)\n", + "\n", + "# 3. Plot full time series with red dashed match boundaries & query overlay\n", + "fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))\n", + "ax1.plot(T, color=\"black\", alpha=0.8)\n", + "ax1.axvline(x=idx, color=\"red\", linestyle=\"--\")\n", + "ax1.axvline(x=idx + len(Q), color=\"red\", linestyle=\"--\")\n", + "ax1.set_ylabel(\"Acceleration\")\n", + "\n", + "ax2.plot(stumpy.core.z_norm(Q), label=\"Query (Carpet Pattern)\", color=\"tab:blue\")\n", + "ax2.plot(stumpy.core.z_norm(T[idx : idx + len(Q)]), label=\"Best Match\", color=\"tab:orange\", linestyle=\"--\")\n", + "ax2.legend()\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "bfa92bf6", + "metadata": {}, + "source": [ + "### Summary\n", + "The two red dashed lines highlight the starting positions of the most similar pair of sub-sequences (motifs) of length $m = 50$." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}