From dc407db86bd014e75c6bff3fa240fe0cb6a81237 Mon Sep 17 00:00:00 2001 From: JulianKimmig Date: Thu, 4 Sep 2025 14:46:12 +0200 Subject: [PATCH] feat(peak_finder): add optional re-centering of peak indices based on selected source - Implemented logic to adjust peak indices using either the original signal or centroid method. - Enhanced peak detection accuracy by allowing for dynamic peak repositioning within specified bounds. --- pyproject.toml | 2 +- src/funcnodes_span/__init__.py | 2 +- src/funcnodes_span/peak_analysis.py | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index caaa005..3b40658 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "funcnodes-span" -version = "1.0.0" +version = "1.0.1" description = "SPectral ANalysis (SPAN) for funcnodes" readme = "README.md" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",] diff --git a/src/funcnodes_span/__init__.py b/src/funcnodes_span/__init__.py index fc052fc..e864b32 100644 --- a/src/funcnodes_span/__init__.py +++ b/src/funcnodes_span/__init__.py @@ -7,7 +7,7 @@ from funcnodes_lmfit import NODE_SHELF as LMFIT_NODE_SHELF from .curves import CURVES_NODE_SHELF -__version__ = "1.0.0" +__version__ = "1.0.1" NODE_SHELF = fn.Shelf( name="Spectral Analysis", diff --git a/src/funcnodes_span/peak_analysis.py b/src/funcnodes_span/peak_analysis.py index 8f88b0d..4b38304 100644 --- a/src/funcnodes_span/peak_analysis.py +++ b/src/funcnodes_span/peak_analysis.py @@ -270,6 +270,27 @@ def peak_finder( if y[peak] > height: peak_lst.append([left_min, peak, right_min]) + # Optionally re-center peak indices based on selected source + if len(peak_lst) > 0: + for k, (i_idx, idx, f_idx) in enumerate(peak_lst): + i = max(0, int(i_idx)) + f = min(len(_y) - 1, int(f_idx)) + if f <= i: + continue + if index_source == "original" and on is not None: + # Use argmax on the original (or differently processed) signal within bounds + local_argmax = int(np.argmax(_y[i : f + 1])) + i + peak_lst[k] = [i_idx, local_argmax, f_idx] + elif index_source == "centroid": + # Center-of-mass within bounds on original signal + yy = _y[i : f + 1] + w = yy - np.min(yy) + w = np.maximum(w, 0) + if np.sum(w) > 0: + cm = int(np.round(np.average(np.arange(i, f + 1), weights=w))) + cm = int(np.clip(cm, i, f)) + peak_lst[k] = [i_idx, cm, f_idx] + peak_properties_list = [] for peak_nr, peak in enumerate(peak_lst):