speckit 1.0.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.
speckit-1.0.0/AUTHORS ADDED
@@ -0,0 +1,2 @@
1
+ Miguel Dovale, University of Arizona (Tucson, Arizona)
2
+ Gerhard Heinzel, Max-Planck Institut für Gravitationsphysik (Hannover, Germany)
speckit-1.0.0/LICENSE ADDED
@@ -0,0 +1,35 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Miguel Dovale (University of Arizona),
4
+ Gerhard Heinzel (Albert Einstein Institute).
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ This software may be subject to U.S. export control laws. By accepting this
32
+ software, the user agrees to comply with all applicable U.S. export laws and
33
+ regulations. User has the responsibility to obtain export licenses, or other
34
+ export authority as may be required before exporting such information to
35
+ foreign countries or providing access to foreign persons.
@@ -0,0 +1,20 @@
1
+ # Include top-level metadata
2
+ include LICENSE
3
+ include README.md
4
+ include AUTHORS
5
+ include pyproject.toml
6
+
7
+ # Ship library source
8
+ graft speckit
9
+
10
+ # Ship tests and examples in sdist
11
+ graft examples
12
+ graft tests
13
+ include tests/*.gz
14
+
15
+ # Exclusions
16
+ prune **/__pycache__
17
+ prune tests/__pycache__
18
+
19
+ # Global ignores
20
+ global-exclude *.py[cod] *.so *.dylib *.dll *.DS_Store
speckit-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.4
2
+ Name: speckit
3
+ Version: 1.0.0
4
+ Summary: A Python toolkit for Spectral Analysis.
5
+ Author: Gerhard Heinzel
6
+ Author-email: Miguel Dovale <mikedovale@pm.me>
7
+ License-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/mdovale/spectools
9
+ Project-URL: Repository, https://github.com/mdovale/spectools
10
+ Project-URL: Issues, https://github.com/mdovale/spectools/issues
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Scientific/Engineering :: Physics
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ License-File: AUTHORS
19
+ Requires-Dist: numpy
20
+ Requires-Dist: scipy
21
+ Requires-Dist: pandas
22
+ Requires-Dist: control
23
+ Requires-Dist: matplotlib
24
+ Requires-Dist: numba
25
+ Requires-Dist: tqdm
26
+ Requires-Dist: py7zr
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest; extra == "dev"
29
+ Requires-Dist: build; extra == "dev"
30
+ Requires-Dist: twine; extra == "dev"
31
+ Requires-Dist: ruff; extra == "dev"
32
+ Dynamic: license-file
33
+
34
+ # SpecKit: Python library for dynamic-resolution spectral analysis
35
+ [Miguel Dovale](https://orcid.org/0000-0002-6300-5226)
36
+ [Gerhard Heinzel](https://orcid.org/0000-0003-1661-7868)
37
+
38
+ **SpecKit** is a high-performance Python toolkit for advanced spectral analysis, designed for scientists and engineers who require high-fidelity, high-dynamic-range spectral estimates.
39
+
40
+ The library's core feature is its **logarithmically-spaced frequency scheduling algorithm**. Unlike traditional methods such as Welch’s, which use a fixed segment length and resolution across all frequencies, SpecKit dynamically adjusts the frequency resolution. The result is that, for a given dataset, this method provides many more high-resolution spectral estimates at low frequencies, while minimizing statistical uncertainty (via more averages) at high frequencies. This method is ideally suited for ana...
41
+
42
+ Built on rigorous, textbook-backed theory, SpecKit also provides **comprehensive error analysis** for all its estimates, making it a reliable tool for scientific research.
43
+
44
+ ---
45
+
46
+ ## Key Features
47
+
48
+ - **Logarithmic Frequency Scheduling**
49
+ Dynamically adapts segment length and averaging to deliver optimal resolution and stability across the entire frequency spectrum.
50
+
51
+ - **High-Performance Engine**
52
+ Leverages [`numba`](https://numba.pydata.org/) for JIT-compiling and parallelizing performance-critical code. Provides pure NumPy fallbacks for full portability.
53
+
54
+ - **Comprehensive Spectral Quantities**
55
+ Calculates a full suite of auto-spectral and cross-spectral estimates, including:
56
+ - Power Spectral Density (PSD) and Amplitude Spectral Density (ASD)
57
+ - Cross Spectral Density (CSD)
58
+ - Transfer Functions and Coherence
59
+ - Conditioned spectra for MISO/SISO systems
60
+
61
+ - **Rigorous Error Analysis**
62
+ Provides analytically derived **standard deviations** and **normalized random errors** for all key estimates, following Bendat & Piersol.
63
+ Additionally, SpecKit computes **empirical errors** directly from segment scatter using Welford-style accumulation (see below).
64
+
65
+ - **Advanced DSP Utilities**
66
+ Includes tools for:
67
+ - Multi-file data loading/resampling
68
+ - High-order Lagrange interpolation for fractional time shifting
69
+ - Optimal linear combination for noise subtraction
70
+ - Specialized flat-top windows with known Equivalent Noise Bandwidth (ENBW)
71
+
72
+ - **High-Quality Noise Generation**
73
+ Ultra-fast, numerically stable generators for white, red (Brownian), pink, and general 1/f^α colored noise.
74
+
75
+ - **Publication-Ready Plotting**
76
+ Built-in, user-friendly plotting interface for creating clear and professional figures.
77
+
78
+ ---
79
+
80
+ ## Installation
81
+
82
+ Install SpecKit directly from PyPI:
83
+
84
+ ```bash
85
+ pip install speckit
86
+ ```
87
+
88
+ For development:
89
+
90
+ ```bash
91
+ git clone https://github.com/mdovale/speckit.git
92
+ cd speckit
93
+ pip install -e .[dev]
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Quickstart
99
+
100
+ The main user-facing function is `speckit.compute_spectrum`.
101
+ Here’s a simple example of computing the Amplitude Spectral Density (ASD) of a noisy signal and comparing it to SciPy’s Welch method:
102
+
103
+ ```python
104
+ import numpy as np
105
+ import matplotlib.pyplot as plt
106
+ from scipy.signal import welch
107
+ from speckit import compute_spectrum
108
+
109
+ N = int(1e6) # samples
110
+ fs = 2.0 # Hz
111
+ x = np.random.randn(N)
112
+
113
+ # Welch (fixed resolution)
114
+ f_welch, psd_welch = welch(x, fs, window="hann", nperseg=N // 8)
115
+
116
+ # SpecKit (dynamic resolution)
117
+ result = compute_spectrum(x, fs=fs, Jdes=1000, Kdes=100, win="Kaiser", psll=200)
118
+
119
+ fig, ax = plt.subplots(figsize=(8, 5), dpi=150)
120
+ ax.loglog(f_welch, np.sqrt(psd_welch), label="Welch", color="gray", alpha=0.7)
121
+ result.plot(which="asd", errors=True, sigma=1, ax=ax, label="SpecKit", color="crimson")
122
+ ax.set_xlabel("Frequency (Hz)")
123
+ ax.set_ylabel(r"ASD (units / $\sqrt{\rm Hz}$)")
124
+ ax.legend()
125
+ ax.grid(True, which="both", linestyle="--", linewidth=0.5)
126
+ plt.show()
127
+ ```
128
+
129
+ ---
130
+
131
+ ## API Overview
132
+
133
+ ### Top-level entry point
134
+ - **`speckit.compute_spectrum(data, fs, **kwargs)`**
135
+ Configures, plans, and executes a spectral analysis in one line.
136
+
137
+ ### Core classes
138
+ - **`SpectrumAnalyzer`**
139
+ Configuration + computation object.
140
+ Methods:
141
+ - `.plan()` → returns frequency/segmentation plan.
142
+ - `.compute()` → full spectrum analysis.
143
+ - `.compute_single_bin(freq, fres or L)` → analyze a single frequency bin.
144
+
145
+ - **`SpectrumResult`**
146
+ Immutable container with all results and helper methods.
147
+ Attributes are lazily computed and cached on demand:
148
+ - `psd`, `asd`, `csd`, `tf`, `coh`, `ENBW`, …
149
+ - Errors: `Gxx_dev`, `Hxy_dev`, `coh_error`, etc.
150
+ - Empirical errors: `XY_emp_dev`, `Gxy_emp_dev`, …
151
+ - Utilities: `.plot()`, `.to_dataframe()`, `.get_rms()`, `.get_measurement()`.
152
+
153
+ ---
154
+
155
+ ## Performance Strategies
156
+
157
+ SpecKit is designed for datasets with millions of samples. Performance comes from:
158
+
159
+ 1. **Numba JIT Kernels**
160
+ - Core bin-by-bin statistics are computed with hand-optimized Goertzel recurrences.
161
+ - Parallelized across segments using `numba.prange`.
162
+
163
+ 2. **Selective Detrending**
164
+ - Order = `-1`: window only
165
+ - Order = `0`: mean removal
166
+ - Order = `1,2`: polynomial detrend via orthonormal basis (`_build_Q`)
167
+ - The detrend mode changes which JIT kernel is dispatched.
168
+
169
+ 3. **Window/Polynomial Caching**
170
+ - Expensive objects like windows and polynomial bases are cached per segment length.
171
+
172
+ 4. **Fallback to NumPy**
173
+ - If Numba is unavailable, pure-NumPy helpers vectorize segment processing.
174
+ - NumPy path uses highly optimized `polyfit`/`polyval` for detrending.
175
+
176
+ 5. **Single-Bin Evaluation**
177
+ - `.compute_single_bin()` avoids planning full spectra and is highly efficient for probing specific frequencies.
178
+
179
+ ---
180
+
181
+ ## Error Analysis and Welford’s Algorithm
182
+
183
+ ### Textbook formulas
184
+ SpecKit implements Bendat & Piersol-style analytic formulas:
185
+ - Variances of PSD, CSD, and coherence estimates scale as `1/√K`, where `K` is the number of averages.
186
+ - Coherence errors scale with `(1 - γ²) / √K`.
187
+
188
+ ### Empirical scatter (M2)
189
+ In addition, the JIT kernels compute:
190
+ - **`MXX`, `MYY`**: mean segment powers
191
+ - **`M2`**: mean squared deviation of per-segment cross-spectra about the mean
192
+
193
+ This is essentially Welford’s algorithm for streaming variance, adapted to complex quantities.
194
+
195
+ From `M2`, SpecKit derives:
196
+ - **`XY_emp_var`**: variance of the averaged cross-spectrum
197
+ - **`XY_emp_dev`**: empirical standard deviation
198
+ - **`Gxx_emp_dev`**, **`Gxy_emp_dev`**: empirical deviations mapped into spectral density units
199
+
200
+ These provide **non-parametric uncertainty estimates**, complementing the analytic formulas. They are particularly useful when:
201
+ - The Gaussian assumptions of textbook theory may not hold
202
+ - Segments are correlated due to overlap
203
+ - One wants to validate that statistical convergence is as expected
204
+
205
+ ### Why both?
206
+ - **Analytic errors** are fast, interpretable, and match the literature.
207
+ - **Empirical errors** reflect actual scatter in the data.
208
+ Together, they provide a complete picture of uncertainty.
209
+
210
+ ---
211
+
212
+ ## References and Acknowledgements
213
+
214
+ 1. **General Spectral Analysis and Uncertainty**
215
+ - Bendat, Piersol. *Random Data: Analysis and Measurement Procedures*. John Wiley & Sons.
216
+ - Bendat, Piersol. *Engineering Applications of Correlation and Spectral Analysis*. John Wiley & Sons.
217
+
218
+ 2. **Logarithmic Frequency Scheduling**
219
+ - Tröbs, M., Heinzel, G. *Improved spectrum estimation from digitized time series on a logarithmic frequency axis*. [doi:10.1016/j.measurement.2005.10.010](https://doi.org/10.1016/j.measurement.2005.10.010)
220
+ - Heinzel, G., Rüdiger, A., & Schilling, R. (2002). *Spectrum and spectral density estimation by the Discrete Fourier transform (DFT), including a comprehensive list of window functions and some new flat-top windows*. Max-Planck-Institut für Gravitationsphysik.
221
+ - Basis for SpecKit’s lpsd_plan and ltf_plan scheduler, inspired by algorithms developed for LISA Pathfinder data analysis.
222
+
223
+ 3. **Colored Noise Generation**
224
+ - Plaszczynski, S. (2007). *Generating long streams of 1/f^α noise*. Fluctuation and Noise Letters. [doi:10.1142/S0219477507003635](https://doi.org/10.1142/S0219477507003635)
225
+ - Provides the stable cascade-of-filters method used in SpecKit.
226
+ - Numba-optimized version of original code by [Jan Waldmann](https://github.com/janwaldmann/pyplnoise)
227
+
228
+ 4. **High-order Lagrange Interpolation**
229
+ - [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8429119.svg)](https://doi.org/10.5281/zenodo.8429119)
230
+ - dsp.timeshift and dsp.lagrange_taps adopted from the PyTDI project. Credit to: [Staab, Martin](https://orcid.org/0000-0001-5036-6586), [Bayle, Jean-Baptiste](https://orcid.org/0000-0001-7629-6555), [Hartwig, Olaf](https://orcid.org/0000-0003-2670-3815)
231
+
232
+ ---
233
+
234
+ ## License
235
+
236
+ BSD 3-Clause License. See the LICENSE file.
237
+
238
+ ---
239
+
240
+ ## Contributing
241
+
242
+ Contributions are welcome!
243
+ Please open issues or PRs for bug reports, feature requests, or ideas.
@@ -0,0 +1,210 @@
1
+ # SpecKit: Python library for dynamic-resolution spectral analysis
2
+ [Miguel Dovale](https://orcid.org/0000-0002-6300-5226)
3
+ [Gerhard Heinzel](https://orcid.org/0000-0003-1661-7868)
4
+
5
+ **SpecKit** is a high-performance Python toolkit for advanced spectral analysis, designed for scientists and engineers who require high-fidelity, high-dynamic-range spectral estimates.
6
+
7
+ The library's core feature is its **logarithmically-spaced frequency scheduling algorithm**. Unlike traditional methods such as Welch’s, which use a fixed segment length and resolution across all frequencies, SpecKit dynamically adjusts the frequency resolution. The result is that, for a given dataset, this method provides many more high-resolution spectral estimates at low frequencies, while minimizing statistical uncertainty (via more averages) at high frequencies. This method is ideally suited for ana...
8
+
9
+ Built on rigorous, textbook-backed theory, SpecKit also provides **comprehensive error analysis** for all its estimates, making it a reliable tool for scientific research.
10
+
11
+ ---
12
+
13
+ ## Key Features
14
+
15
+ - **Logarithmic Frequency Scheduling**
16
+ Dynamically adapts segment length and averaging to deliver optimal resolution and stability across the entire frequency spectrum.
17
+
18
+ - **High-Performance Engine**
19
+ Leverages [`numba`](https://numba.pydata.org/) for JIT-compiling and parallelizing performance-critical code. Provides pure NumPy fallbacks for full portability.
20
+
21
+ - **Comprehensive Spectral Quantities**
22
+ Calculates a full suite of auto-spectral and cross-spectral estimates, including:
23
+ - Power Spectral Density (PSD) and Amplitude Spectral Density (ASD)
24
+ - Cross Spectral Density (CSD)
25
+ - Transfer Functions and Coherence
26
+ - Conditioned spectra for MISO/SISO systems
27
+
28
+ - **Rigorous Error Analysis**
29
+ Provides analytically derived **standard deviations** and **normalized random errors** for all key estimates, following Bendat & Piersol.
30
+ Additionally, SpecKit computes **empirical errors** directly from segment scatter using Welford-style accumulation (see below).
31
+
32
+ - **Advanced DSP Utilities**
33
+ Includes tools for:
34
+ - Multi-file data loading/resampling
35
+ - High-order Lagrange interpolation for fractional time shifting
36
+ - Optimal linear combination for noise subtraction
37
+ - Specialized flat-top windows with known Equivalent Noise Bandwidth (ENBW)
38
+
39
+ - **High-Quality Noise Generation**
40
+ Ultra-fast, numerically stable generators for white, red (Brownian), pink, and general 1/f^α colored noise.
41
+
42
+ - **Publication-Ready Plotting**
43
+ Built-in, user-friendly plotting interface for creating clear and professional figures.
44
+
45
+ ---
46
+
47
+ ## Installation
48
+
49
+ Install SpecKit directly from PyPI:
50
+
51
+ ```bash
52
+ pip install speckit
53
+ ```
54
+
55
+ For development:
56
+
57
+ ```bash
58
+ git clone https://github.com/mdovale/speckit.git
59
+ cd speckit
60
+ pip install -e .[dev]
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Quickstart
66
+
67
+ The main user-facing function is `speckit.compute_spectrum`.
68
+ Here’s a simple example of computing the Amplitude Spectral Density (ASD) of a noisy signal and comparing it to SciPy’s Welch method:
69
+
70
+ ```python
71
+ import numpy as np
72
+ import matplotlib.pyplot as plt
73
+ from scipy.signal import welch
74
+ from speckit import compute_spectrum
75
+
76
+ N = int(1e6) # samples
77
+ fs = 2.0 # Hz
78
+ x = np.random.randn(N)
79
+
80
+ # Welch (fixed resolution)
81
+ f_welch, psd_welch = welch(x, fs, window="hann", nperseg=N // 8)
82
+
83
+ # SpecKit (dynamic resolution)
84
+ result = compute_spectrum(x, fs=fs, Jdes=1000, Kdes=100, win="Kaiser", psll=200)
85
+
86
+ fig, ax = plt.subplots(figsize=(8, 5), dpi=150)
87
+ ax.loglog(f_welch, np.sqrt(psd_welch), label="Welch", color="gray", alpha=0.7)
88
+ result.plot(which="asd", errors=True, sigma=1, ax=ax, label="SpecKit", color="crimson")
89
+ ax.set_xlabel("Frequency (Hz)")
90
+ ax.set_ylabel(r"ASD (units / $\sqrt{\rm Hz}$)")
91
+ ax.legend()
92
+ ax.grid(True, which="both", linestyle="--", linewidth=0.5)
93
+ plt.show()
94
+ ```
95
+
96
+ ---
97
+
98
+ ## API Overview
99
+
100
+ ### Top-level entry point
101
+ - **`speckit.compute_spectrum(data, fs, **kwargs)`**
102
+ Configures, plans, and executes a spectral analysis in one line.
103
+
104
+ ### Core classes
105
+ - **`SpectrumAnalyzer`**
106
+ Configuration + computation object.
107
+ Methods:
108
+ - `.plan()` → returns frequency/segmentation plan.
109
+ - `.compute()` → full spectrum analysis.
110
+ - `.compute_single_bin(freq, fres or L)` → analyze a single frequency bin.
111
+
112
+ - **`SpectrumResult`**
113
+ Immutable container with all results and helper methods.
114
+ Attributes are lazily computed and cached on demand:
115
+ - `psd`, `asd`, `csd`, `tf`, `coh`, `ENBW`, …
116
+ - Errors: `Gxx_dev`, `Hxy_dev`, `coh_error`, etc.
117
+ - Empirical errors: `XY_emp_dev`, `Gxy_emp_dev`, …
118
+ - Utilities: `.plot()`, `.to_dataframe()`, `.get_rms()`, `.get_measurement()`.
119
+
120
+ ---
121
+
122
+ ## Performance Strategies
123
+
124
+ SpecKit is designed for datasets with millions of samples. Performance comes from:
125
+
126
+ 1. **Numba JIT Kernels**
127
+ - Core bin-by-bin statistics are computed with hand-optimized Goertzel recurrences.
128
+ - Parallelized across segments using `numba.prange`.
129
+
130
+ 2. **Selective Detrending**
131
+ - Order = `-1`: window only
132
+ - Order = `0`: mean removal
133
+ - Order = `1,2`: polynomial detrend via orthonormal basis (`_build_Q`)
134
+ - The detrend mode changes which JIT kernel is dispatched.
135
+
136
+ 3. **Window/Polynomial Caching**
137
+ - Expensive objects like windows and polynomial bases are cached per segment length.
138
+
139
+ 4. **Fallback to NumPy**
140
+ - If Numba is unavailable, pure-NumPy helpers vectorize segment processing.
141
+ - NumPy path uses highly optimized `polyfit`/`polyval` for detrending.
142
+
143
+ 5. **Single-Bin Evaluation**
144
+ - `.compute_single_bin()` avoids planning full spectra and is highly efficient for probing specific frequencies.
145
+
146
+ ---
147
+
148
+ ## Error Analysis and Welford’s Algorithm
149
+
150
+ ### Textbook formulas
151
+ SpecKit implements Bendat & Piersol-style analytic formulas:
152
+ - Variances of PSD, CSD, and coherence estimates scale as `1/√K`, where `K` is the number of averages.
153
+ - Coherence errors scale with `(1 - γ²) / √K`.
154
+
155
+ ### Empirical scatter (M2)
156
+ In addition, the JIT kernels compute:
157
+ - **`MXX`, `MYY`**: mean segment powers
158
+ - **`M2`**: mean squared deviation of per-segment cross-spectra about the mean
159
+
160
+ This is essentially Welford’s algorithm for streaming variance, adapted to complex quantities.
161
+
162
+ From `M2`, SpecKit derives:
163
+ - **`XY_emp_var`**: variance of the averaged cross-spectrum
164
+ - **`XY_emp_dev`**: empirical standard deviation
165
+ - **`Gxx_emp_dev`**, **`Gxy_emp_dev`**: empirical deviations mapped into spectral density units
166
+
167
+ These provide **non-parametric uncertainty estimates**, complementing the analytic formulas. They are particularly useful when:
168
+ - The Gaussian assumptions of textbook theory may not hold
169
+ - Segments are correlated due to overlap
170
+ - One wants to validate that statistical convergence is as expected
171
+
172
+ ### Why both?
173
+ - **Analytic errors** are fast, interpretable, and match the literature.
174
+ - **Empirical errors** reflect actual scatter in the data.
175
+ Together, they provide a complete picture of uncertainty.
176
+
177
+ ---
178
+
179
+ ## References and Acknowledgements
180
+
181
+ 1. **General Spectral Analysis and Uncertainty**
182
+ - Bendat, Piersol. *Random Data: Analysis and Measurement Procedures*. John Wiley & Sons.
183
+ - Bendat, Piersol. *Engineering Applications of Correlation and Spectral Analysis*. John Wiley & Sons.
184
+
185
+ 2. **Logarithmic Frequency Scheduling**
186
+ - Tröbs, M., Heinzel, G. *Improved spectrum estimation from digitized time series on a logarithmic frequency axis*. [doi:10.1016/j.measurement.2005.10.010](https://doi.org/10.1016/j.measurement.2005.10.010)
187
+ - Heinzel, G., Rüdiger, A., & Schilling, R. (2002). *Spectrum and spectral density estimation by the Discrete Fourier transform (DFT), including a comprehensive list of window functions and some new flat-top windows*. Max-Planck-Institut für Gravitationsphysik.
188
+ - Basis for SpecKit’s lpsd_plan and ltf_plan scheduler, inspired by algorithms developed for LISA Pathfinder data analysis.
189
+
190
+ 3. **Colored Noise Generation**
191
+ - Plaszczynski, S. (2007). *Generating long streams of 1/f^α noise*. Fluctuation and Noise Letters. [doi:10.1142/S0219477507003635](https://doi.org/10.1142/S0219477507003635)
192
+ - Provides the stable cascade-of-filters method used in SpecKit.
193
+ - Numba-optimized version of original code by [Jan Waldmann](https://github.com/janwaldmann/pyplnoise)
194
+
195
+ 4. **High-order Lagrange Interpolation**
196
+ - [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8429119.svg)](https://doi.org/10.5281/zenodo.8429119)
197
+ - dsp.timeshift and dsp.lagrange_taps adopted from the PyTDI project. Credit to: [Staab, Martin](https://orcid.org/0000-0001-5036-6586), [Bayle, Jean-Baptiste](https://orcid.org/0000-0001-7629-6555), [Hartwig, Olaf](https://orcid.org/0000-0003-2670-3815)
198
+
199
+ ---
200
+
201
+ ## License
202
+
203
+ BSD 3-Clause License. See the LICENSE file.
204
+
205
+ ---
206
+
207
+ ## Contributing
208
+
209
+ Contributions are welcome!
210
+ Please open issues or PRs for bug reports, feature requests, or ideas.
@@ -0,0 +1,101 @@
1
+ # BSD 3-Clause License
2
+
3
+ # Copyright (c) 2025, Miguel Dovale (University of Arizona),
4
+ # Gerhard Heinzel (Albert Einstein Institute).
5
+
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+
9
+ # 1. Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+
16
+ # 3. Neither the name of the copyright holder nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ # This software may be subject to U.S. export control laws. By accepting this
32
+ # software, the user agrees to comply with all applicable U.S. export laws and
33
+ # regulations. User has the responsibility to obtain export licenses, or other
34
+ # export authority as may be required before exporting such information to
35
+ # foreign countries or providing access to foreign persons.
36
+ #
37
+ import numpy as np
38
+ import matplotlib.pyplot as plt
39
+ from scipy import signal
40
+ from speckit import SpectrumAnalyzer
41
+ from speckit.noise import band_limited_noise
42
+
43
+ if __name__ == "__main__":
44
+ N = int(1e6) # Size of the example time series
45
+ fs = 2.0 # Sampling frequency
46
+
47
+ x1 = (
48
+ 1e-6 * band_limited_noise(1e-6, 1e0, N, fs)
49
+ + 1e3 * band_limited_noise(1e-3, 10e-3, N, fs)
50
+ + 1e3 * band_limited_noise(50e-3, 60e-3, N, fs)
51
+ )
52
+ fig, ax = plt.subplots(figsize=(16, 4), dpi=150)
53
+ ax.set_xlabel("Sample")
54
+ ax.set_ylabel("Signal")
55
+ ax.plot(x1, color="black")
56
+ plt.show(block=False)
57
+
58
+ f1, psd = signal.welch(
59
+ x1,
60
+ fs=fs,
61
+ window=("kaiser", 30),
62
+ nperseg=int(N),
63
+ noverlap=int(N / 2),
64
+ scaling="density",
65
+ return_onesided=True,
66
+ )
67
+
68
+ # 1. Configure the analyzer
69
+ print("Configuring SpectrumAnalyzer...")
70
+ analyzer = SpectrumAnalyzer(
71
+ data=x1,
72
+ fs=fs,
73
+ bmin=1.0,
74
+ order=-1,
75
+ win="Kaiser",
76
+ Jdes=1000,
77
+ psll=200,
78
+ verbose=True,
79
+ )
80
+
81
+ # 2. (Optional) Inspect the plan before computation
82
+ plan = analyzer.plan()
83
+ print(f"\nGenerated a plan with {plan['nf']} frequency bins.")
84
+
85
+ # 3. Create a multiprocessing pool and run the computation
86
+ print("\nStarting computation...")
87
+ result = analyzer.compute()
88
+
89
+ print("\nComputation complete!")
90
+ print(f"Result object type: {type(result)}")
91
+
92
+ fig, ax = plt.subplots(figsize=(6, 4), dpi=150)
93
+ ax.set_xlabel("Fourier frequency (Hz)")
94
+ ax.set_ylabel(r"Spectral density (units $/\sqrt{\rm Hz}$)")
95
+ ax.loglog(f1, np.sqrt(psd), label="Welch", color="gray")
96
+ result.plot(which="asd", ax=ax, label="LPSD")
97
+ ax.legend()
98
+ fig.tight_layout()
99
+ plt.show()
100
+
101
+ print("Done!")