dsgbr 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dsgbr-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Ricardo Frantz
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dsgbr-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,252 @@
1
+ Metadata-Version: 2.4
2
+ Name: dsgbr
3
+ Version: 0.1.0
4
+ Summary: Dual Savitzky–Golay Baseline Ratio (DSGBR) spectral peak detector
5
+ Author: Ricardo Frantz
6
+ Maintainer: Ricardo Frantz
7
+ License-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/ricardofrantz/dsgbr
9
+ Project-URL: Source, https://github.com/ricardofrantz/dsgbr
10
+ Project-URL: Tracker, https://github.com/ricardofrantz/dsgbr/issues
11
+ Project-URL: Documentation, https://github.com/ricardofrantz/dsgbr#readme
12
+ Keywords: spectral-analysis,peak-detection,signal-processing,savitzky-golay,power-spectral-density,fluid-dynamics
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Education
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numpy>=1.24
28
+ Requires-Dist: scipy>=1.10
29
+ Provides-Extra: plotting
30
+ Requires-Dist: matplotlib>=3.7; extra == "plotting"
31
+ Provides-Extra: tests
32
+ Requires-Dist: coverage[toml]>=7.5.3; extra == "tests"
33
+ Requires-Dist: hypothesis>=6.100; extra == "tests"
34
+ Requires-Dist: pytest-cov>=5.0.0; extra == "tests"
35
+ Requires-Dist: pytest>=8.2.2; extra == "tests"
36
+ Provides-Extra: tests-extra
37
+ Requires-Dist: pytest-randomly==3.16.0; extra == "tests-extra"
38
+ Requires-Dist: pytest-rerunfailures==15.1; extra == "tests-extra"
39
+ Requires-Dist: pytest-xdist==3.8.0; extra == "tests-extra"
40
+ Provides-Extra: qa
41
+ Requires-Dist: codespell>=2.4.1; extra == "qa"
42
+ Requires-Dist: mypy>=1.11.0; extra == "qa"
43
+ Requires-Dist: pre-commit>=3.8.0; extra == "qa"
44
+ Requires-Dist: ruff>=0.7.0; extra == "qa"
45
+ Provides-Extra: dev
46
+ Requires-Dist: build; extra == "dev"
47
+ Requires-Dist: coverage[toml]>=7.5.3; extra == "dev"
48
+ Requires-Dist: codespell>=2.4.1; extra == "dev"
49
+ Requires-Dist: hypothesis>=6.100; extra == "dev"
50
+ Requires-Dist: mypy>=1.11.0; extra == "dev"
51
+ Requires-Dist: pre-commit>=3.8.0; extra == "dev"
52
+ Requires-Dist: pytest>=8.2.2; extra == "dev"
53
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
54
+ Requires-Dist: pytest-randomly==3.16.0; extra == "dev"
55
+ Requires-Dist: pytest-rerunfailures==15.1; extra == "dev"
56
+ Requires-Dist: pytest-xdist==3.8.0; extra == "dev"
57
+ Requires-Dist: ruff>=0.7.0; extra == "dev"
58
+ Requires-Dist: twine; extra == "dev"
59
+ Dynamic: license-file
60
+
61
+ # DSGBR
62
+
63
+ [![CI](https://github.com/ricardofrantz/dsgbr/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ricardofrantz/dsgbr/actions/workflows/ci.yml)
64
+ [![codecov](https://codecov.io/gh/ricardofrantz/dsgbr/branch/master/graph/badge.svg)](https://codecov.io/gh/ricardofrantz/dsgbr)
65
+ [![PyPI](https://img.shields.io/pypi/v/dsgbr.svg)](https://pypi.org/project/dsgbr/)
66
+ [![Python](https://img.shields.io/pypi/pyversions/dsgbr.svg)](https://pypi.org/project/dsgbr/)
67
+ [![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)
68
+
69
+ **Dual Savitzky-Golay Baseline Ratio (DSGBR)** is a spectral peak detector
70
+ for frequency-domain signals. It was designed for robust detection in dense,
71
+ noisy power spectra common in fluid dynamics, vibration analysis, and other
72
+ experimental sciences.
73
+
74
+ ## Algorithm
75
+
76
+ ```
77
+ PSD ──► SEARCH (short-scale SG smooth)
78
+
79
+
80
+ BASELINE (long-scale SG smooth)
81
+
82
+
83
+ RATIO = SEARCH / BASELINE
84
+
85
+
86
+ peaks where RATIO ≥ threshold
87
+
88
+ ├──► spacing rules
89
+ ├──► ULF guardrail
90
+ └──► band selection (if > max_peaks)
91
+
92
+
93
+ (peak_frequencies, peak_heights)
94
+ ```
95
+
96
+ The detector builds a short-scale **SEARCH** signal and a longer-scale
97
+ **BASELINE** signal using Savitzky-Golay filtering. A peak is accepted
98
+ when `SEARCH / BASELINE` exceeds a configurable ratio threshold, subject
99
+ to spacing constraints and an ultra-low-frequency guardrail.
100
+
101
+ ## Install
102
+
103
+ ```bash
104
+ pip install dsgbr
105
+ ```
106
+
107
+ For development:
108
+
109
+ ```bash
110
+ git clone https://github.com/ricardofrantz/dsgbr.git
111
+ cd dsgbr
112
+ uv pip install -e ".[dev]"
113
+ ```
114
+
115
+ ## Quick start
116
+
117
+ ```python
118
+ import numpy as np
119
+ from dsgbr import dsgbr_detector
120
+
121
+ # Synthetic PSD with known peaks
122
+ frequencies = np.linspace(0.001, 1.0, 2048)
123
+ psd = np.ones_like(frequencies)
124
+ psd[400] = 12.0 # inject a peak
125
+ psd[1200] = 8.0 # inject another
126
+
127
+ peak_f, peak_h = dsgbr_detector(
128
+ frequencies, psd,
129
+ case_info={"ratio_threshold": 1.5, "baseline_window": 61},
130
+ )
131
+ print(f"Detected {peak_f.size} peaks at f = {peak_f}")
132
+ ```
133
+
134
+ ## Configuration
135
+
136
+ All parameters are set through `DetectionConfig` or passed as a dictionary
137
+ via the `case_info` argument. Short aliases (RT, SW, BWF, etc.) are
138
+ supported for concise configuration.
139
+
140
+ | Parameter | Alias | Default | Description |
141
+ |-----------|-------|---------|-------------|
142
+ | `ratio_threshold` | RT | 1.8 | Min SEARCH/BASELINE ratio for acceptance |
143
+ | `smooth_window` | SW | 3 | Savitzky-Golay window for SEARCH (odd, >= 3) |
144
+ | `baseline_window_frac` | BWF | 0.001 | Baseline window as fraction of data length |
145
+ | `distance_low` | DL | 2 | Min bin separation below `switch_frequency` |
146
+ | `distance_high` | DH | 1 | Min bin separation above `switch_frequency` |
147
+ | `switch_frequency` | SF | 0.02 | Frequency threshold for spacing rules |
148
+ | `max_peaks` | MP | 25 | Maximum peaks returned |
149
+ | `smooth_polyorder` | — | 2 | Polynomial order for SG filter |
150
+ | `smooth_on_log` | — | True | Smooth log10(PSD) instead of linear |
151
+ | `baseline_window` | — | None | Fixed baseline window (overrides BWF) |
152
+ | `baseline_on_log` | — | True | Baseline smoothing in log domain |
153
+ | `band_strategy` | — | proportional | Band allocation: proportional or equal |
154
+ | `n_bands` | — | 10 | Number of logarithmic frequency bands |
155
+ | `ulf_fmax` | — | 0.001 | ULF band upper frequency limit |
156
+ | `ulf_min_q` | — | 9.0 | Minimum Q-factor for ULF peaks |
157
+ | `ulf_max_points` | — | 5 | Maximum ULF peaks to retain |
158
+
159
+ ## Advanced usage
160
+
161
+ ### Support series for visualization
162
+
163
+ ```python
164
+ from dsgbr import compute_support_series
165
+
166
+ support = compute_support_series(frequencies, psd, case_info={"RT": 2.0})
167
+
168
+ # Plot SEARCH vs BASELINE overlay
169
+ import matplotlib.pyplot as plt
170
+ plt.semilogy(frequencies, support["search_series"], label="SEARCH")
171
+ plt.semilogy(frequencies, support["baseline_series"], label="BASELINE")
172
+ plt.semilogy(frequencies, support["rthreshold"], "--", label="Threshold")
173
+ plt.legend()
174
+ plt.show()
175
+ ```
176
+
177
+ ### Band-balanced peak selection
178
+
179
+ ```python
180
+ from dsgbr import select_peaks_by_frequency_bands
181
+
182
+ # Reduce 100 peaks to 15, spread across frequency bands
183
+ sel_f, sel_h = select_peaks_by_frequency_bands(
184
+ peak_frequencies, peak_heights,
185
+ max_peaks=15, strategy="proportional", n_bands=8,
186
+ )
187
+ ```
188
+
189
+ ### Configuration via dataclass
190
+
191
+ ```python
192
+ from dsgbr import DetectionConfig
193
+
194
+ cfg = DetectionConfig(ratio_threshold=2.5, smooth_window=7, max_peaks=10)
195
+ print(cfg.to_metadata())
196
+ ```
197
+
198
+ ## API reference
199
+
200
+ | Function / Class | Description |
201
+ |-----------------|-------------|
202
+ | `dsgbr_detector(f, psd, *, case_info, return_support)` | Main detection pipeline |
203
+ | `compute_support_series(f, psd, case_info)` | Return intermediate arrays for visualization |
204
+ | `select_peaks_by_frequency_bands(f, h, *, max_peaks, strategy, n_bands)` | Band-balanced down-selection |
205
+ | `find_nearest_frequency(target, frequencies, heights)` | Closest detected frequency lookup |
206
+ | `DetectionConfig` | Frozen dataclass with 17 parameters |
207
+ | `detect_peaks_case_adaptive(...)` | Deprecated alias for `dsgbr_detector` |
208
+ | `DSGBR_PARAM_ALIASES` | Short-to-long parameter name mapping |
209
+
210
+ ## Examples
211
+
212
+ See [`examples/`](examples/) for runnable scripts:
213
+
214
+ - **`basic_usage.py`** — minimal detection example
215
+ - **`parameter_tuning.py`** — sweep ratio_threshold, compare peak counts
216
+ - **`visualization.py`** — SEARCH/BASELINE overlay plot
217
+
218
+ ## How it works
219
+
220
+ DSGBR applies two Savitzky-Golay passes at different scales to separate
221
+ sharp spectral peaks from the slowly varying baseline. The ratio between
222
+ these two series naturally highlights peaks above the local background,
223
+ making the detector robust to spectral slope and broadband noise. For a
224
+ detailed description, see [`docs/algorithm.md`](docs/algorithm.md).
225
+
226
+ ## Citation
227
+
228
+ If you use DSGBR in your research, please cite:
229
+
230
+ ```bibtex
231
+ @software{dsgbr2026,
232
+ author = {Frantz, Ricardo},
233
+ title = {{DSGBR}: Dual Savitzky--Golay Baseline Ratio spectral peak detector},
234
+ year = {2026},
235
+ url = {https://github.com/ricardofrantz/dsgbr},
236
+ }
237
+ ```
238
+
239
+ ## License
240
+
241
+ BSD 3-Clause. See [LICENSE](LICENSE).
242
+
243
+ ## Contributing
244
+
245
+ Contributions are welcome. Please open an issue to discuss changes before
246
+ submitting a pull request. Run the full QA suite before submitting:
247
+
248
+ ```bash
249
+ uv pip install -e ".[dev]"
250
+ pre-commit run --all-files
251
+ pytest --cov=dsgbr
252
+ ```
dsgbr-0.1.0/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # DSGBR
2
+
3
+ [![CI](https://github.com/ricardofrantz/dsgbr/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ricardofrantz/dsgbr/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/ricardofrantz/dsgbr/branch/master/graph/badge.svg)](https://codecov.io/gh/ricardofrantz/dsgbr)
5
+ [![PyPI](https://img.shields.io/pypi/v/dsgbr.svg)](https://pypi.org/project/dsgbr/)
6
+ [![Python](https://img.shields.io/pypi/pyversions/dsgbr.svg)](https://pypi.org/project/dsgbr/)
7
+ [![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)
8
+
9
+ **Dual Savitzky-Golay Baseline Ratio (DSGBR)** is a spectral peak detector
10
+ for frequency-domain signals. It was designed for robust detection in dense,
11
+ noisy power spectra common in fluid dynamics, vibration analysis, and other
12
+ experimental sciences.
13
+
14
+ ## Algorithm
15
+
16
+ ```
17
+ PSD ──► SEARCH (short-scale SG smooth)
18
+
19
+
20
+ BASELINE (long-scale SG smooth)
21
+
22
+
23
+ RATIO = SEARCH / BASELINE
24
+
25
+
26
+ peaks where RATIO ≥ threshold
27
+
28
+ ├──► spacing rules
29
+ ├──► ULF guardrail
30
+ └──► band selection (if > max_peaks)
31
+
32
+
33
+ (peak_frequencies, peak_heights)
34
+ ```
35
+
36
+ The detector builds a short-scale **SEARCH** signal and a longer-scale
37
+ **BASELINE** signal using Savitzky-Golay filtering. A peak is accepted
38
+ when `SEARCH / BASELINE` exceeds a configurable ratio threshold, subject
39
+ to spacing constraints and an ultra-low-frequency guardrail.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install dsgbr
45
+ ```
46
+
47
+ For development:
48
+
49
+ ```bash
50
+ git clone https://github.com/ricardofrantz/dsgbr.git
51
+ cd dsgbr
52
+ uv pip install -e ".[dev]"
53
+ ```
54
+
55
+ ## Quick start
56
+
57
+ ```python
58
+ import numpy as np
59
+ from dsgbr import dsgbr_detector
60
+
61
+ # Synthetic PSD with known peaks
62
+ frequencies = np.linspace(0.001, 1.0, 2048)
63
+ psd = np.ones_like(frequencies)
64
+ psd[400] = 12.0 # inject a peak
65
+ psd[1200] = 8.0 # inject another
66
+
67
+ peak_f, peak_h = dsgbr_detector(
68
+ frequencies, psd,
69
+ case_info={"ratio_threshold": 1.5, "baseline_window": 61},
70
+ )
71
+ print(f"Detected {peak_f.size} peaks at f = {peak_f}")
72
+ ```
73
+
74
+ ## Configuration
75
+
76
+ All parameters are set through `DetectionConfig` or passed as a dictionary
77
+ via the `case_info` argument. Short aliases (RT, SW, BWF, etc.) are
78
+ supported for concise configuration.
79
+
80
+ | Parameter | Alias | Default | Description |
81
+ |-----------|-------|---------|-------------|
82
+ | `ratio_threshold` | RT | 1.8 | Min SEARCH/BASELINE ratio for acceptance |
83
+ | `smooth_window` | SW | 3 | Savitzky-Golay window for SEARCH (odd, >= 3) |
84
+ | `baseline_window_frac` | BWF | 0.001 | Baseline window as fraction of data length |
85
+ | `distance_low` | DL | 2 | Min bin separation below `switch_frequency` |
86
+ | `distance_high` | DH | 1 | Min bin separation above `switch_frequency` |
87
+ | `switch_frequency` | SF | 0.02 | Frequency threshold for spacing rules |
88
+ | `max_peaks` | MP | 25 | Maximum peaks returned |
89
+ | `smooth_polyorder` | — | 2 | Polynomial order for SG filter |
90
+ | `smooth_on_log` | — | True | Smooth log10(PSD) instead of linear |
91
+ | `baseline_window` | — | None | Fixed baseline window (overrides BWF) |
92
+ | `baseline_on_log` | — | True | Baseline smoothing in log domain |
93
+ | `band_strategy` | — | proportional | Band allocation: proportional or equal |
94
+ | `n_bands` | — | 10 | Number of logarithmic frequency bands |
95
+ | `ulf_fmax` | — | 0.001 | ULF band upper frequency limit |
96
+ | `ulf_min_q` | — | 9.0 | Minimum Q-factor for ULF peaks |
97
+ | `ulf_max_points` | — | 5 | Maximum ULF peaks to retain |
98
+
99
+ ## Advanced usage
100
+
101
+ ### Support series for visualization
102
+
103
+ ```python
104
+ from dsgbr import compute_support_series
105
+
106
+ support = compute_support_series(frequencies, psd, case_info={"RT": 2.0})
107
+
108
+ # Plot SEARCH vs BASELINE overlay
109
+ import matplotlib.pyplot as plt
110
+ plt.semilogy(frequencies, support["search_series"], label="SEARCH")
111
+ plt.semilogy(frequencies, support["baseline_series"], label="BASELINE")
112
+ plt.semilogy(frequencies, support["rthreshold"], "--", label="Threshold")
113
+ plt.legend()
114
+ plt.show()
115
+ ```
116
+
117
+ ### Band-balanced peak selection
118
+
119
+ ```python
120
+ from dsgbr import select_peaks_by_frequency_bands
121
+
122
+ # Reduce 100 peaks to 15, spread across frequency bands
123
+ sel_f, sel_h = select_peaks_by_frequency_bands(
124
+ peak_frequencies, peak_heights,
125
+ max_peaks=15, strategy="proportional", n_bands=8,
126
+ )
127
+ ```
128
+
129
+ ### Configuration via dataclass
130
+
131
+ ```python
132
+ from dsgbr import DetectionConfig
133
+
134
+ cfg = DetectionConfig(ratio_threshold=2.5, smooth_window=7, max_peaks=10)
135
+ print(cfg.to_metadata())
136
+ ```
137
+
138
+ ## API reference
139
+
140
+ | Function / Class | Description |
141
+ |-----------------|-------------|
142
+ | `dsgbr_detector(f, psd, *, case_info, return_support)` | Main detection pipeline |
143
+ | `compute_support_series(f, psd, case_info)` | Return intermediate arrays for visualization |
144
+ | `select_peaks_by_frequency_bands(f, h, *, max_peaks, strategy, n_bands)` | Band-balanced down-selection |
145
+ | `find_nearest_frequency(target, frequencies, heights)` | Closest detected frequency lookup |
146
+ | `DetectionConfig` | Frozen dataclass with 17 parameters |
147
+ | `detect_peaks_case_adaptive(...)` | Deprecated alias for `dsgbr_detector` |
148
+ | `DSGBR_PARAM_ALIASES` | Short-to-long parameter name mapping |
149
+
150
+ ## Examples
151
+
152
+ See [`examples/`](examples/) for runnable scripts:
153
+
154
+ - **`basic_usage.py`** — minimal detection example
155
+ - **`parameter_tuning.py`** — sweep ratio_threshold, compare peak counts
156
+ - **`visualization.py`** — SEARCH/BASELINE overlay plot
157
+
158
+ ## How it works
159
+
160
+ DSGBR applies two Savitzky-Golay passes at different scales to separate
161
+ sharp spectral peaks from the slowly varying baseline. The ratio between
162
+ these two series naturally highlights peaks above the local background,
163
+ making the detector robust to spectral slope and broadband noise. For a
164
+ detailed description, see [`docs/algorithm.md`](docs/algorithm.md).
165
+
166
+ ## Citation
167
+
168
+ If you use DSGBR in your research, please cite:
169
+
170
+ ```bibtex
171
+ @software{dsgbr2026,
172
+ author = {Frantz, Ricardo},
173
+ title = {{DSGBR}: Dual Savitzky--Golay Baseline Ratio spectral peak detector},
174
+ year = {2026},
175
+ url = {https://github.com/ricardofrantz/dsgbr},
176
+ }
177
+ ```
178
+
179
+ ## License
180
+
181
+ BSD 3-Clause. See [LICENSE](LICENSE).
182
+
183
+ ## Contributing
184
+
185
+ Contributions are welcome. Please open an issue to discuss changes before
186
+ submitting a pull request. Run the full QA suite before submitting:
187
+
188
+ ```bash
189
+ uv pip install -e ".[dev]"
190
+ pre-commit run --all-files
191
+ pytest --cov=dsgbr
192
+ ```
@@ -0,0 +1,123 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "dsgbr"
7
+ version = "0.1.0"
8
+ description = "Dual Savitzky–Golay Baseline Ratio (DSGBR) spectral peak detector"
9
+ readme = { file = "README.md", content-type = "text/markdown" }
10
+ requires-python = ">=3.10"
11
+ license = "BSD-3-Clause"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Ricardo Frantz" }]
14
+ maintainers = [{ name = "Ricardo Frantz" }]
15
+ dependencies = [
16
+ "numpy>=1.24",
17
+ "scipy>=1.10",
18
+ ]
19
+ keywords = [
20
+ "spectral-analysis",
21
+ "peak-detection",
22
+ "signal-processing",
23
+ "savitzky-golay",
24
+ "power-spectral-density",
25
+ "fluid-dynamics",
26
+ ]
27
+ classifiers = [
28
+ "Development Status :: 4 - Beta",
29
+ "Intended Audience :: Education",
30
+ "Intended Audience :: Science/Research",
31
+ "Operating System :: OS Independent",
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3 :: Only",
34
+ "Programming Language :: Python :: 3.10",
35
+ "Programming Language :: Python :: 3.11",
36
+ "Programming Language :: Python :: 3.12",
37
+ "Topic :: Scientific/Engineering",
38
+ "Typing :: Typed",
39
+ ]
40
+
41
+ [project.optional-dependencies]
42
+ plotting = [
43
+ "matplotlib>=3.7",
44
+ ]
45
+ tests = [
46
+ "coverage[toml]>=7.5.3",
47
+ "hypothesis>=6.100",
48
+ "pytest-cov>=5.0.0",
49
+ "pytest>=8.2.2",
50
+ ]
51
+ tests-extra = [
52
+ "pytest-randomly==3.16.0",
53
+ "pytest-rerunfailures==15.1",
54
+ "pytest-xdist==3.8.0",
55
+ ]
56
+ qa = [
57
+ "codespell>=2.4.1",
58
+ "mypy>=1.11.0",
59
+ "pre-commit>=3.8.0",
60
+ "ruff>=0.7.0",
61
+ ]
62
+ dev = [
63
+ "build",
64
+ "coverage[toml]>=7.5.3",
65
+ "codespell>=2.4.1",
66
+ "hypothesis>=6.100",
67
+ "mypy>=1.11.0",
68
+ "pre-commit>=3.8.0",
69
+ "pytest>=8.2.2",
70
+ "pytest-cov>=5.0.0",
71
+ "pytest-randomly==3.16.0",
72
+ "pytest-rerunfailures==15.1",
73
+ "pytest-xdist==3.8.0",
74
+ "ruff>=0.7.0",
75
+ "twine",
76
+ ]
77
+
78
+ [project.urls]
79
+ Homepage = "https://github.com/ricardofrantz/dsgbr"
80
+ Source = "https://github.com/ricardofrantz/dsgbr"
81
+ Tracker = "https://github.com/ricardofrantz/dsgbr/issues"
82
+ Documentation = "https://github.com/ricardofrantz/dsgbr#readme"
83
+
84
+ [tool.setuptools.packages.find]
85
+ where = ["src"]
86
+
87
+ [tool.ruff]
88
+ line-length = 100
89
+ target-version = "py310"
90
+ extend-exclude = ["docs/conf.py"]
91
+
92
+ [tool.ruff.lint]
93
+ select = ["E", "F", "I", "B", "UP", "SIM", "RUF", "D"]
94
+ ignore = ["E501", "D100", "D104"]
95
+
96
+ [tool.ruff.lint.pydocstyle]
97
+ convention = "numpy"
98
+
99
+ [tool.ruff.lint.extend-per-file-ignores]
100
+ "__init__.py" = ["F401"]
101
+ "tests/*" = ["D"]
102
+ "examples/*" = ["D"]
103
+
104
+ [tool.mypy]
105
+ pretty = true
106
+ strict = true
107
+ python_version = "3.10"
108
+ exclude = ["docs/conf.py"]
109
+
110
+ [tool.codespell]
111
+ skip = "docs/conf.py"
112
+ check-filenames = true
113
+
114
+ [tool.coverage.run]
115
+ branch = true
116
+ relative_files = true
117
+ source = ["dsgbr"]
118
+ omit = ["*/__pycache__/*"]
119
+
120
+ [tool.coverage.report]
121
+ fail_under = 90
122
+ precision = 2
123
+ show_missing = true
dsgbr-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,29 @@
1
+ """Backward-compatibility shim for ``from dsgbr.DSGBR import ...``.
2
+
3
+ This module re-exports the full public API so that existing call sites
4
+ (e.g. ``from dsgbr.DSGBR import dsgbr_detector``) continue to work
5
+ unchanged after the package restructure.
6
+ """
7
+
8
+ from dsgbr._compat import (
9
+ DSGBR_PARAM_ALIASES,
10
+ DSGBRDetectionConfig,
11
+ detect_peaks_case_adaptive,
12
+ )
13
+ from dsgbr._config import DetectionConfig
14
+ from dsgbr._detector import compute_support_series, dsgbr_detector
15
+ from dsgbr._selection import (
16
+ find_nearest_frequency,
17
+ select_peaks_by_frequency_bands,
18
+ )
19
+
20
+ __all__ = [
21
+ "DSGBR_PARAM_ALIASES",
22
+ "DSGBRDetectionConfig",
23
+ "DetectionConfig",
24
+ "compute_support_series",
25
+ "detect_peaks_case_adaptive",
26
+ "dsgbr_detector",
27
+ "find_nearest_frequency",
28
+ "select_peaks_by_frequency_bands",
29
+ ]
@@ -0,0 +1,35 @@
1
+ """Dual Savitzky-Golay Baseline Ratio (DSGBR) spectral peak detector.
2
+
3
+ The DSGBR detector applies two Savitzky-Golay smoothing passes -- one to build
4
+ the SEARCH series, another to obtain a broader BASELINE -- and accepts peaks
5
+ where the SEARCH/BASELINE ratio exceeds a configurable threshold.
6
+
7
+ Public API
8
+ ----------
9
+ .. autosummary::
10
+ DetectionConfig
11
+ dsgbr_detector
12
+ compute_support_series
13
+ select_peaks_by_frequency_bands
14
+ find_nearest_frequency
15
+ detect_peaks_case_adaptive
16
+ DSGBRDetectionConfig
17
+ DSGBR_PARAM_ALIASES
18
+ """
19
+
20
+ from dsgbr._compat import DSGBR_PARAM_ALIASES, DSGBRDetectionConfig, detect_peaks_case_adaptive
21
+ from dsgbr._config import DetectionConfig
22
+ from dsgbr._detector import compute_support_series, dsgbr_detector
23
+ from dsgbr._selection import find_nearest_frequency, select_peaks_by_frequency_bands
24
+
25
+ __version__ = "0.1.0"
26
+ __all__ = [
27
+ "DSGBR_PARAM_ALIASES",
28
+ "DSGBRDetectionConfig",
29
+ "DetectionConfig",
30
+ "compute_support_series",
31
+ "detect_peaks_case_adaptive",
32
+ "dsgbr_detector",
33
+ "find_nearest_frequency",
34
+ "select_peaks_by_frequency_bands",
35
+ ]