STUMPY is a powerful and scalable Python library for modern time series analysis
This report summarizes scanner evidence for stumpy-dev/stumpy, a Python project with 4,160 GitHub stars. SynthScan examined 72,212 lines of code across 128 source files, recording 399 pattern matches distributed across 11 syntactic categories. The legacy adjusted pattern signal is 6.8 (Moderate pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 372 finding(s).
Are imports declared and package/API names verified? 1 finding(s).
Are wrappers, guards, and repeated structures necessary? 319 finding(s).
Which changes need focused human review? 399 finding(s).
Run additional scans to build a history of the legacy pattern signal. Score changes are not a measure of AI adoption or code quality.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 399 distinct pattern matches across 11 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | versions.py | 52 | def get_all_python_versions_in_range(start, stop): | CODE |
| LOW | versions.py | 78 | def get_min_numba_numpy_version(min_python): | CODE |
| LOW⚡ | versions.py | 135 | def check_python_compatibility(row, min_python): | CODE |
| LOW⚡ | versions.py | 143 | def check_scipy_compatibility(row, min_python, min_numpy): | CODE |
| LOW⚡ | versions.py | 152 | def get_scipy_version_df_backup(): | CODE |
| LOW | versions.py | 269 | def get_minor_versions_between(start_version_str, end_version_str): | CODE |
| LOW | versions.py | 310 | def get_latest_scipy_python_version(): | CODE |
| LOW | versions.py | 318 | def get_latest_pkg_python_version(pkg): | CODE |
| LOW | versions.py | 347 | def get_latest_numpy_versions(n=10): | CODE |
| LOW | fastmath.py | 428 | def check_call_stack_fastmath(pkg_dir, pkg_name): | CODE |
| LOW | stumpy/maamp.py | 303 | def _maamp_multi_distance_profile( | CODE |
| LOW | stumpy/maamp.py | 397 | def maamp_multi_distance_profile(query_idx, T, m, include=None, discords=False, p=2.0): | CODE |
| LOW | stumpy/core.py | 289 | def _gpu_searchsorted_left_dnf(*args, **kwargs): # pragma: no cover | CODE |
| LOW | stumpy/core.py | 304 | def _gpu_searchsorted_right_dnf(*args, **kwargs): # pragma: no cover | CODE |
| LOW | stumpy/core.py | 1060 | def _calculate_squared_distance( | CODE |
| LOW | stumpy/core.py | 1128 | def _calculate_squared_distance_profile( | CODE |
| LOW | stumpy/core.py | 1194 | def calculate_distance_profile( | CODE |
| LOW | stumpy/core.py | 1418 | def _mass_absolute_distance_matrix(Q, T, m, distance_matrix, p=2.0): | CODE |
| LOW | stumpy/core.py | 1455 | def mueen_calculate_distance_profile(Q, T): | CODE |
| LOW | stumpy/core.py | 2175 | def preprocess_non_normalized(T, m, copy=True): | CODE |
| LOW | stumpy/core.py | 2650 | def fix_isconstant_isfinite_conflicts( | CODE |
| LOW | stumpy/mstump.py | 658 | def _get_first_mstump_profile( | CODE |
| LOW | stumpy/aampdist_snippets.py | 13 | def _get_all_aampdist_profiles( | CODE |
| LOW | stumpy/sdp.py | 28 | def _njit_sliding_dot_product(Q, T): | CODE |
| LOW | stumpy/sdp.py | 57 | def _convolve_sliding_dot_product(Q, T): | CODE |
| LOW | stumpy/sdp.py | 77 | def _oaconvolve_sliding_dot_product(Q, T): | CODE |
| LOW | stumpy/sdp.py | 97 | def _pocketfft_sliding_dot_product(Q, T): | CODE |
| LOW | stumpy/sdp.py | 129 | def _make_pyfftw_sliding_dot_product(init_len=2**20, real_dtype="float64"): | CODE |
| LOW | stumpy/ostinato.py | 13 | def _across_series_nearest_neighbors( | CODE |
| LOW | stumpy/aamp_ostinato.py | 12 | def _aamp_across_series_nearest_neighbors( | CODE |
| LOW | tests/test_maamped.py | 87 | def test_maamped_include_discords(T, m, dask_cluster): | CODE |
| LOW | tests/test_maamped.py | 117 | def test_maamped_constant_subsequence_self_join(dask_cluster): | CODE |
| LOW | tests/test_maamped.py | 134 | def test_maamped_identical_subsequence_self_join(dask_cluster): | CODE |
| LOW | tests/test_maamped.py | 156 | def test_maamped_one_subsequence_inf_self_join_first_dimension( | CODE |
| LOW | tests/test_maamped.py | 175 | def test_maamped_one_subsequence_inf_self_join_all_dimensions( | CODE |
| LOW | tests/test_maamped.py | 194 | def test_maamped_one_subsequence_nan_self_join_first_dimension( | CODE |
| LOW | tests/test_maamped.py | 213 | def test_maamped_one_subsequence_nan_self_join_all_dimensions( | CODE |
| LOW | tests/test_gpu_aamp.py | 78 | def test_gpu_aamp_self_join_larger_window(T_A, T_B, m): | CODE |
| LOW | tests/test_gpu_aamp.py | 123 | def test_parallel_gpu_aamp_self_join(T_A, T_B): | CODE |
| LOW | tests/test_gpu_aamp.py | 185 | def test_gpu_aamp_constant_subsequence_self_join(): | CODE |
| LOW | tests/test_gpu_aamp.py | 268 | def test_gpu_aamp_identical_subsequence_self_join(): | CODE |
| LOW | tests/test_gpu_aamp.py | 340 | def test_gpu_aamp_nan_inf_self_join(T_A, T_B, substitute_B, substitution_locations): | CODE |
| LOW | tests/test_gpu_aamp.py | 401 | def test_gpu_aamp_nan_zero_mean_self_join(): | CODE |
| LOW | tests/test_gpu_stump.py | 78 | def test_gpu_stump_self_join_larger_window(T_A, T_B, m): | CODE |
| LOW | tests/test_gpu_stump.py | 120 | def test_parallel_gpu_stump_self_join(T_A, T_B): | CODE |
| LOW | tests/test_gpu_stump.py | 182 | def test_gpu_stump_constant_subsequence_self_join(): | CODE |
| LOW | tests/test_gpu_stump.py | 265 | def test_gpu_stump_identical_subsequence_self_join(): | CODE |
| LOW | tests/test_gpu_stump.py | 337 | def test_gpu_stump_nan_inf_self_join(T_A, T_B, substitute_B, substitution_locations): | CODE |
| LOW | tests/test_gpu_stump.py | 398 | def test_gpu_stump_nan_zero_mean_self_join(): | CODE |
| LOW | tests/test_gpu_stump.py | 453 | def test_gpu_stump_self_join_custom_isconstant(T_A, T_B): | CODE |
| LOW | tests/test_floss.py | 449 | def test_floss_with_isconstant(): | CODE |
| LOW | tests/test_mstump.py | 23 | def naive_rolling_window_dot_product(Q, T): | CODE |
| LOW | tests/test_mstump.py | 103 | def test_multi_distance_profile(T, m): | CODE |
| LOW | tests/test_mstump.py | 114 | def test_get_first_mstump_profile(T, m): | CODE |
| LOW | tests/test_mstump.py | 198 | def test_subspace_include_discords(T, m): | CODE |
| LOW | tests/test_mstump.py | 284 | def test_mstump_include_discords(T, m): | CODE |
| LOW | tests/test_mstump.py | 322 | def test_mstump_wrapper_include(T, m): | CODE |
| LOW | tests/test_mstump.py | 342 | def test_constant_subsequence_self_join(): | CODE |
| LOW | tests/test_mstump.py | 355 | def test_identical_subsequence_self_join(): | CODE |
| LOW | tests/test_mstump.py | 376 | def test_mstump_nan_inf_self_join_first_dimension( | CODE |
| 220 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | stumpy/__init__.py | 295 | except Exception: | CODE |
| HIGH | stumpy/__init__.py | 292 | except AttributeError: | CODE |
| HIGH | stumpy/core.py | 21 | except ImportError: | CODE |
| HIGH | tests/test_maamped.py | 24 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_stumped.py | 27 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_mpdist.py | 25 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_aamped.py | 24 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_aamp_stimp.py | 30 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_ostinato.py | 26 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_stimp.py | 30 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_non_normalized_decorator.py | 77 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_aamp_ostinato.py | 24 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_aampdist.py | 23 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| HIGH | tests/test_mstumped.py | 26 | except tornado.ioloop.TimeoutError: # pragma: no cover | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | versions.py | 172 | CODE | |
| LOW | versions.py | 475 | CODE | |
| LOW | versions.py | 528 | CODE | |
| LOW | fastmath.py | 9 | CODE | |
| LOW | fastmath.py | 392 | CODE | |
| LOW | fastmath.py | 168 | CODE | |
| LOW | stumpy/chains.py | 75 | CODE | |
| LOW | stumpy/cache.py | 21 | CODE | |
| LOW | stumpy/__init__.py | 66 | CODE | |
| LOW | stumpy/core.py | 71 | CODE | |
| LOW | stumpy/core.py | 971 | CODE | |
| LOW | stumpy/core.py | 2880 | CODE | |
| LOW | stumpy/core.py | 3285 | CODE | |
| LOW | stumpy/core.py | 3358 | CODE | |
| LOW | stumpy/core.py | 132 | CODE | |
| LOW | stumpy/core.py | 134 | CODE | |
| LOW | stumpy/stump.py | 20 | CODE | |
| LOW | stumpy/scraamp.py | 87 | CODE | |
| LOW | stumpy/scrump.py | 137 | CODE | |
| LOW | stumpy/gpu_stump.py | 21 | CODE | |
| LOW | stumpy/ostinato.py | 148 | CODE | |
| LOW | stumpy/aamp.py | 18 | CODE | |
| LOW | stumpy/aamp_ostinato.py | 138 | CODE | |
| LOW | tests/test_floss.py | 51 | CODE | |
| LOW | tests/test_floss.py | 449 | CODE | |
| LOW | tests/test_scrump.py | 863 | CODE | |
| LOW | tests/test_stumpi.py | 884 | CODE | |
| LOW | tests/test_core.py | 60 | CODE | |
| LOW | tests/test_core.py | 100 | CODE | |
| LOW | tests/test_core.py | 938 | CODE | |
| LOW | tests/test_aampi.py | 19 | CODE | |
| LOW | tests/test_aampi.py | 1024 | CODE | |
| LOW | tests/test_aampi.py | 1110 | CODE | |
| LOW | tests/naive.py | 131 | CODE | |
| LOW | tests/naive.py | 225 | CODE | |
| LOW | tests/naive.py | 347 | CODE | |
| LOW | tests/naive.py | 458 | CODE | |
| LOW | tests/naive.py | 1115 | CODE | |
| LOW | tests/naive.py | 1796 | CODE | |
| LOW | tests/naive.py | 1892 | CODE | |
| LOW | tests/naive.py | 1981 | CODE | |
| LOW | tests/naive.py | 2055 | CODE | |
| LOW | tests/naive.py | 2195 | CODE | |
| LOW | tests/naive.py | 981 | CODE | |
| LOW | tests/test_sdp.py | 132 | CODE | |
| LOW | tests/test_ostinato.py | 213 | CODE | |
| LOW | tests/test_scraamp.py | 379 | CODE | |
| LOW | tests/test_scraamp.py | 423 | CODE | |
| LOW | tests/test_scraamp.py | 703 | CODE | |
| LOW | tests/test_scraamp.py | 722 | CODE | |
| LOW | tests/test_scraamp.py | 740 | CODE | |
| LOW | tests/test_scraamp.py | 778 | CODE | |
| LOW | tests/test_scraamp.py | 816 | CODE | |
| LOW | tests/test_aamp_ostinato.py | 168 | CODE | |
| LOW | tests/test_motifs.py | 13 | CODE | |
| LOW | tests/test_motifs.py | 87 | CODE | |
| LOW | tests/test_motifs.py | 120 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | stumpy/scraamp.py | 0 | get the (top-k) matrix profile. when `k=1` (default), the output is a 1d array consisting of the matrix profile. when `k | STRING |
| HIGH | stumpy/scrump.py | 0 | get the (top-k) matrix profile. when `k=1` (default), the output is a 1d array consisting of the matrix profile. when `k | STRING |
| HIGH | stumpy/stumpi.py | 0 | get the (top-k) matrix profile. when `k=1` (default), the output is a 1d array consisting of the matrix profile. when `k | STRING |
| HIGH | stumpy/aampi.py | 0 | get the (top-k) matrix profile. when `k=1` (default), the output is a 1d array consisting of the matrix profile. when `k | STRING |
| HIGH | stumpy/scraamp.py | 0 | get the (top-1) left matrix profile indices parameters ---------- none returns ------- out : numpy.ndarray the (top-1) l | STRING |
| HIGH | stumpy/scrump.py | 0 | get the (top-1) left matrix profile indices parameters ---------- none returns ------- out : numpy.ndarray the (top-1) l | STRING |
| HIGH | stumpy/stumpi.py | 0 | get the (top-1) left matrix profile indices parameters ---------- none returns ------- out : numpy.ndarray the (top-1) l | STRING |
| HIGH | stumpy/aampi.py | 0 | get the (top-1) left matrix profile indices parameters ---------- none returns ------- out : numpy.ndarray the (top-1) l | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pypi.sh | 1 | #!/bin/sh | COMMENT |
| LOW | pypi.sh | 21 | # the tar.gz file (click "view details"): https://pypi.org/project/stumpy/#files | COMMENT |
| LOW | pypi.sh | 41 | # PyPI Stats - https://packaging.python.org/guides/analyzing-pypi-package-downloads/ | COMMENT |
| LOW | pypi.sh | 81 | else | COMMENT |
| LOW | pypi.sh | 101 | # password = <PyPI API Token> | COMMENT |
| LOW | stumpy/__init__.py | 301 | # Expose lazy names in dir() for discoverability | COMMENT |
| LOW | stumpy/core.py | 601 | # the central-most subsequence must be located outside the `excl_zone`, | COMMENT |
| LOW | stumpy/core.py | 621 | # at index 4. In both cases, the relative (index-wise) distance is 2, | COMMENT |
| LOW | stumpy/sdp.py | 281 | # Let T' and Q' denote the zero-padded versions of T and Q[::-1], | COMMENT |
| LOW | stumpy/sdp.py | 301 | # applied either before or after the transform: | COMMENT |
| LOW | tests/test_scrump.py | 941 | # (`S_i`). Also, we denote `P[i]` as their corresponding distances sorted in | COMMENT |
| LOW | tests/test_core.py | 1881 | # assertion | COMMENT |
| LOW | tests/naive.py | 2301 | COMMENT | |
| LOW | tests/test_sdp.py | 21 | # are considered: | COMMENT |
| LOW | docs/conf.py | 1 | # -*- coding: utf-8 -*- | COMMENT |
| LOW | docs/conf.py | 141 | # to template names. | COMMENT |
| LOW | docs/conf.py | 161 | latex_elements = { | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | versions.py | 336 | CODE | |
| LOW | stumpy/chains.py | 72 | CODE | |
| LOW | stumpy/stimp.py | 123 | CODE | |
| LOW | stumpy/stimp.py | 508 | CODE | |
| LOW | stumpy/aamp_mmotifs.py | 14 | CODE | |
| LOW | stumpy/core.py | 1604 | CODE | |
| LOW | stumpy/motifs.py | 166 | CODE | |
| LOW | stumpy/motifs.py | 404 | CODE | |
| LOW | stumpy/mmotifs.py | 22 | CODE | |
| LOW | stumpy/stamp.py | 247 | CODE | |
| LOW | stumpy/scrump.py | 782 | CODE | |
| LOW | stumpy/aamp_stimp.py | 130 | CODE | |
| LOW | stumpy/gpu_stump.py | 483 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | stumpy/floss.py | 757 | # and so the aforementioned check is all `False` as soon as we start using | COMMENT |
| MEDIUM | tests/naive.py | 2310 | # keeping top-k largest with the aforementioned priority rules is the same as | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | stumpy/core.py | 2850 | msg += "expected (i.e., a negative index is considered null)." | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | stumpy/__init__.py | 295 | except Exception: | CODE |
| LOW | stumpy/cuda.py | 24 | except Exception: | CODE |
| LOW | tests/test_sdp.py | 126 | except Exception as e: # pragma: no cover | CODE |
| LOW | tests/test_sdp.py | 151 | except Exception as e: # pragma: no cover | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test.sh | 120 | # Check if there are any naive implementations not at start of test file | COMMENT |
| LOW | test.sh | 144 | # Check if file does not exist OR file is empty | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | stumpy/sdp.py | 1 | # This file contains different implementations of | COMMENT |