specplotter 1.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.
- specplotter-1.1.0/LICENSE +21 -0
- specplotter-1.1.0/PKG-INFO +509 -0
- specplotter-1.1.0/README.md +474 -0
- specplotter-1.1.0/pyproject.toml +80 -0
- specplotter-1.1.0/setup.cfg +4 -0
- specplotter-1.1.0/specplotter/__init__.py +17 -0
- specplotter-1.1.0/specplotter/cli.py +195 -0
- specplotter-1.1.0/specplotter/specplotter.py +528 -0
- specplotter-1.1.0/specplotter.egg-info/PKG-INFO +509 -0
- specplotter-1.1.0/specplotter.egg-info/SOURCES.txt +14 -0
- specplotter-1.1.0/specplotter.egg-info/dependency_links.txt +1 -0
- specplotter-1.1.0/specplotter.egg-info/entry_points.txt +2 -0
- specplotter-1.1.0/specplotter.egg-info/requires.txt +10 -0
- specplotter-1.1.0/specplotter.egg-info/top_level.txt +1 -0
- specplotter-1.1.0/tests/test_cli.py +26 -0
- specplotter-1.1.0/tests/test_specplotter.py +215 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UT SALT Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: specplotter
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: A tool for creating wideband spectrograms with signal analysis
|
|
5
|
+
Author-email: Your Name <your.email@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/juice500ml/specplotter
|
|
8
|
+
Project-URL: Documentation, https://github.com/juice500ml/specplotter#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/juice500ml/specplotter
|
|
10
|
+
Project-URL: Issues, https://github.com/juice500ml/specplotter/issues
|
|
11
|
+
Keywords: spectrogram,audio,signal-processing,librosa,scipy
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: numpy>=1.19.0
|
|
26
|
+
Requires-Dist: scipy>=1.5.0
|
|
27
|
+
Requires-Dist: librosa>=0.8.0
|
|
28
|
+
Requires-Dist: matplotlib>=3.3.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
33
|
+
Requires-Dist: python-semantic-release[build]; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# SpecPlotter
|
|
37
|
+
|
|
38
|
+
A Python package for creating wideband and narrowband spectrograms with comprehensive signal analysis features.
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- **Wideband and narrowband spectrogram generation** - Switch between analysis modes
|
|
43
|
+
- **Modular signal processing** - Compute individual features independently
|
|
44
|
+
- **Flexible plotting** - Choose which components to display
|
|
45
|
+
- **Zero crossing rate analysis** - Optional ZCR visualization
|
|
46
|
+
- **Energy analysis** - Total energy and low-frequency energy calculations
|
|
47
|
+
- **Waveform visualization** - Optional waveform display
|
|
48
|
+
- **Fully configurable** - All parameters are customizable
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install specplotter
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
### Command Line Interface
|
|
59
|
+
|
|
60
|
+
The easiest way to use SpecPlotter is via the command line:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Basic spectrogram (PNG)
|
|
64
|
+
specplotter audio.wav -o output.png
|
|
65
|
+
|
|
66
|
+
# Basic spectrogram (PDF)
|
|
67
|
+
specplotter audio.wav -o output.pdf
|
|
68
|
+
|
|
69
|
+
# Full analysis with all components
|
|
70
|
+
specplotter audio.wav -o output.pdf --zcr --total-energy --lowfreq-energy --waveform
|
|
71
|
+
|
|
72
|
+
# Narrowband mode
|
|
73
|
+
specplotter audio.wav -o output.png --mode narrowband
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Python API
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from specplotter import SpecPlotter
|
|
80
|
+
import librosa
|
|
81
|
+
|
|
82
|
+
# Load an audio file
|
|
83
|
+
signal, sr = librosa.load('audio.wav', sr=16000)
|
|
84
|
+
|
|
85
|
+
# Create a SpecPlotter instance (default: wideband mode)
|
|
86
|
+
plotter = SpecPlotter()
|
|
87
|
+
|
|
88
|
+
# Plot spectrogram only (default behavior)
|
|
89
|
+
plotter.plot_spectrogram(signal)
|
|
90
|
+
|
|
91
|
+
# Or save to file
|
|
92
|
+
plotter.plot_spectrogram(signal, outfile='spectrogram.png')
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Usage Examples
|
|
96
|
+
|
|
97
|
+
### Basic Usage
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from specplotter import SpecPlotter
|
|
101
|
+
import librosa
|
|
102
|
+
|
|
103
|
+
signal, sr = librosa.load('audio.wav', sr=16000)
|
|
104
|
+
plotter = SpecPlotter()
|
|
105
|
+
|
|
106
|
+
# Default: spectrogram only
|
|
107
|
+
plotter.plot_spectrogram(signal)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Wideband vs Narrowband
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Wideband mode (default)
|
|
114
|
+
plotter_wide = SpecPlotter(mode='wideband')
|
|
115
|
+
|
|
116
|
+
# Narrowband mode
|
|
117
|
+
plotter_narrow = SpecPlotter(mode='narrowband')
|
|
118
|
+
|
|
119
|
+
# Plot with different modes
|
|
120
|
+
plotter_wide.plot_spectrogram(signal)
|
|
121
|
+
plotter_narrow.plot_spectrogram(signal)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Flexible Plotting with Optional Components
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
# Plot with all components
|
|
128
|
+
plotter.plot(
|
|
129
|
+
signal,
|
|
130
|
+
show_zcr=True,
|
|
131
|
+
show_total_energy=True,
|
|
132
|
+
show_lowfreq_energy=True,
|
|
133
|
+
show_waveform=True
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Just spectrogram and waveform
|
|
137
|
+
plotter.plot(signal, show_waveform=True)
|
|
138
|
+
|
|
139
|
+
# Spectrogram with zero crossing rate
|
|
140
|
+
plotter.plot(signal, show_zcr=True)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Using Custom Axes
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
import matplotlib.pyplot as plt
|
|
147
|
+
|
|
148
|
+
# Single axis (spectrogram only)
|
|
149
|
+
fig, ax = plt.subplots()
|
|
150
|
+
plotter.plot_spectrogram(signal, ax=ax)
|
|
151
|
+
|
|
152
|
+
# List of axes matching number of plots
|
|
153
|
+
fig, axes = plt.subplots(3, 1) # For zcr, spectrogram, waveform
|
|
154
|
+
plotter.plot(
|
|
155
|
+
signal,
|
|
156
|
+
ax=list(axes),
|
|
157
|
+
show_zcr=True,
|
|
158
|
+
show_waveform=True
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Full plot with all components
|
|
162
|
+
fig, axes = plt.subplots(5, 1)
|
|
163
|
+
plotter.plot(
|
|
164
|
+
signal,
|
|
165
|
+
ax=list(axes),
|
|
166
|
+
show_zcr=True,
|
|
167
|
+
show_total_energy=True,
|
|
168
|
+
show_lowfreq_energy=True,
|
|
169
|
+
show_waveform=True
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Note:** When providing a list of axes, they must be in this order:
|
|
174
|
+
1. `zcr` (if `show_zcr=True`)
|
|
175
|
+
2. `total_energy` (if `show_total_energy=True`)
|
|
176
|
+
3. `lowfreq_energy` (if `show_lowfreq_energy=True`)
|
|
177
|
+
4. `spectrogram` (always included)
|
|
178
|
+
5. `waveform` (if `show_waveform=True`)
|
|
179
|
+
|
|
180
|
+
### Computing Features Without Plotting
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
# Compute all features
|
|
184
|
+
features = plotter.compute_spectrogram(signal)
|
|
185
|
+
|
|
186
|
+
# Access individual features
|
|
187
|
+
processed_signal = features['processed_signal']
|
|
188
|
+
spectrogram = features['spectrogram']
|
|
189
|
+
zcr = features['zcr']
|
|
190
|
+
total_energy = features['total_energy']
|
|
191
|
+
lowfreq_energy = features['lowfreq_energy']
|
|
192
|
+
|
|
193
|
+
# Use features independently
|
|
194
|
+
import matplotlib.pyplot as plt
|
|
195
|
+
fig, ax = plt.subplots()
|
|
196
|
+
plotter._plot_spectrogram_on_axis(spectrogram, len(signal), ax=ax)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Individual Plotting Methods
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
features = plotter.compute_spectrogram(signal)
|
|
203
|
+
|
|
204
|
+
# Plot individual components
|
|
205
|
+
fig, ax = plt.subplots()
|
|
206
|
+
plotter.plot_zcr(features['zcr'], ax=ax)
|
|
207
|
+
|
|
208
|
+
fig, ax = plt.subplots()
|
|
209
|
+
plotter.plot_total_energy(features['total_energy'], ax=ax)
|
|
210
|
+
|
|
211
|
+
fig, ax = plt.subplots()
|
|
212
|
+
plotter.plot_lowfreq_energy(features['lowfreq_energy'], ax=ax)
|
|
213
|
+
|
|
214
|
+
fig, ax = plt.subplots()
|
|
215
|
+
plotter.plot_waveform(features['processed_signal'], ax=ax)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Configuration
|
|
219
|
+
|
|
220
|
+
### Mode Selection
|
|
221
|
+
|
|
222
|
+
The `mode` parameter sets default window sizes for wideband or narrowband analysis:
|
|
223
|
+
|
|
224
|
+
- **Wideband** (default): `window_size=0.004`, `window_stride=0.001`
|
|
225
|
+
- **Narrowband**: `window_size=0.025`, `window_stride=0.01`
|
|
226
|
+
|
|
227
|
+
### Customizing Parameters
|
|
228
|
+
|
|
229
|
+
All parameters can be customized when creating a SpecPlotter instance:
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
plotter = SpecPlotter(
|
|
233
|
+
mode='wideband', # 'wideband' or 'narrowband'
|
|
234
|
+
sample_rate=16000, # Sample rate (Hz)
|
|
235
|
+
fnotch=60, # Notch filter frequency (Hz)
|
|
236
|
+
notchQ=30, # Notch filter Q factor
|
|
237
|
+
preemphasis_coeff=0.97, # Pre-emphasis coefficient
|
|
238
|
+
window_size=0.004, # Window size (seconds), optional
|
|
239
|
+
window_stride=0.001, # Window stride (seconds), optional
|
|
240
|
+
n_fft=1024, # Number of FFT points
|
|
241
|
+
window=scipy.signal.windows.hamming, # Window function
|
|
242
|
+
db_spread=60, # Dynamic range (dB)
|
|
243
|
+
db_cutoff=3, # Minimum dB value
|
|
244
|
+
fig_height=10, # Figure height (inches)
|
|
245
|
+
inches_per_sec=10, # Horizontal scaling
|
|
246
|
+
zcr_smoothing_std=6, # ZCR smoothing std dev
|
|
247
|
+
zcr_smoothing_size=41, # ZCR smoothing kernel size
|
|
248
|
+
lowfreq_min=125, # Low freq energy min (Hz)
|
|
249
|
+
lowfreq_max=750, # Low freq energy max (Hz)
|
|
250
|
+
)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Overriding Mode Defaults
|
|
254
|
+
|
|
255
|
+
You can override mode defaults by explicitly providing `window_size` and `window_stride`:
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
# Use wideband mode but with custom window settings
|
|
259
|
+
plotter = SpecPlotter(
|
|
260
|
+
mode='wideband',
|
|
261
|
+
window_size=0.005, # Override default
|
|
262
|
+
window_stride=0.002 # Override default
|
|
263
|
+
)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Command Line Interface
|
|
267
|
+
|
|
268
|
+
SpecPlotter includes a command-line interface for quick spectrogram generation.
|
|
269
|
+
|
|
270
|
+
### Basic Usage
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
specplotter <input_file> -o <output_file>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The output format (PNG or PDF) is automatically determined from the file extension.
|
|
277
|
+
|
|
278
|
+
### Options
|
|
279
|
+
|
|
280
|
+
**Required:**
|
|
281
|
+
- `input_file`: Path to input WAV file
|
|
282
|
+
- `-o, --output`: Output file path (must have .png or .pdf extension)
|
|
283
|
+
|
|
284
|
+
**Analysis Mode:**
|
|
285
|
+
- `--mode {wideband,narrowband}`: Analysis mode (default: wideband)
|
|
286
|
+
|
|
287
|
+
**Additional Plots:**
|
|
288
|
+
- `--all`: Show all additional plots (zcr, total-energy, lowfreq-energy, waveform)
|
|
289
|
+
- `--zcr`: Show zero crossing rate plot
|
|
290
|
+
- `--total-energy`: Show total energy plot
|
|
291
|
+
- `--lowfreq-energy`: Show low frequency energy plot
|
|
292
|
+
- `--waveform`: Show waveform plot
|
|
293
|
+
|
|
294
|
+
**Audio Settings:**
|
|
295
|
+
- `--sample-rate FLOAT`: Sample rate in Hz (default: 16000)
|
|
296
|
+
|
|
297
|
+
**Processing Parameters:**
|
|
298
|
+
- `--fnotch FLOAT`: Notch filter frequency in Hz (default: 60)
|
|
299
|
+
- `--notch-q FLOAT`: Notch filter Q factor (default: 30)
|
|
300
|
+
- `--db-spread FLOAT`: Dynamic range in dB (default: 60)
|
|
301
|
+
- `--db-cutoff FLOAT`: Minimum dB value to display (default: 3)
|
|
302
|
+
|
|
303
|
+
### Examples
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# Basic spectrogram
|
|
307
|
+
specplotter audio.wav -o spectrogram.png
|
|
308
|
+
|
|
309
|
+
# Full analysis (all components)
|
|
310
|
+
specplotter audio.wav -o analysis.pdf --all
|
|
311
|
+
|
|
312
|
+
# Narrowband mode with custom settings
|
|
313
|
+
specplotter audio.wav -o output.pdf --mode narrowband --db-spread 80
|
|
314
|
+
|
|
315
|
+
# Custom sample rate
|
|
316
|
+
specplotter audio.wav -o output.png --sample-rate 22050
|
|
317
|
+
|
|
318
|
+
# European line noise (50 Hz instead of 60 Hz)
|
|
319
|
+
specplotter audio.wav -o output.pdf --fnotch 50
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Help
|
|
323
|
+
|
|
324
|
+
For full help and all options:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
specplotter --help
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## API Reference
|
|
331
|
+
|
|
332
|
+
### `SpecPlotter.__init__()`
|
|
333
|
+
|
|
334
|
+
Initialize SpecPlotter with configurable parameters. See Configuration section above for all parameters.
|
|
335
|
+
|
|
336
|
+
### `compute_spectrogram(signal)`
|
|
337
|
+
|
|
338
|
+
Compute spectrogram and related features.
|
|
339
|
+
|
|
340
|
+
**Parameters:**
|
|
341
|
+
- `signal` (np.ndarray): Input audio signal
|
|
342
|
+
|
|
343
|
+
**Returns:**
|
|
344
|
+
- `dict`: Dictionary containing:
|
|
345
|
+
- `'processed_signal'`: Preprocessed signal
|
|
346
|
+
- `'spectrogram'`: Clipped log spectrogram
|
|
347
|
+
- `'zcr'`: Zero crossing rate
|
|
348
|
+
- `'total_energy'`: Total energy envelope
|
|
349
|
+
- `'lowfreq_energy'`: Low frequency energy envelope
|
|
350
|
+
|
|
351
|
+
### `plot(signal, ax=None, show_zcr=False, show_total_energy=False, show_lowfreq_energy=False, show_waveform=False, outfile=None, **kwargs)`
|
|
352
|
+
|
|
353
|
+
Plot spectrogram with optional additional features.
|
|
354
|
+
|
|
355
|
+
**Parameters:**
|
|
356
|
+
- `signal` (np.ndarray): Input audio signal
|
|
357
|
+
- `ax` (Axes or list of Axes, optional): Matplotlib axes to plot on
|
|
358
|
+
- `show_zcr` (bool): Whether to show zero crossing rate plot
|
|
359
|
+
- `show_total_energy` (bool): Whether to show total energy plot
|
|
360
|
+
- `show_lowfreq_energy` (bool): Whether to show low frequency energy plot
|
|
361
|
+
- `show_waveform` (bool): Whether to show waveform plot
|
|
362
|
+
- `outfile` (str, optional): If provided, save figure to file
|
|
363
|
+
- `**kwargs`: Additional keyword arguments passed to plotting functions
|
|
364
|
+
|
|
365
|
+
**Returns:**
|
|
366
|
+
- `tuple`: (figure, axes_dict)
|
|
367
|
+
|
|
368
|
+
### `plot_spectrogram(signal, ax=None, outfile=None, **kwargs)`
|
|
369
|
+
|
|
370
|
+
Plot spectrogram only (convenience method).
|
|
371
|
+
|
|
372
|
+
**Parameters:**
|
|
373
|
+
- `signal` (np.ndarray): Input audio signal
|
|
374
|
+
- `ax` (Axes, optional): Matplotlib axes to plot on
|
|
375
|
+
- `outfile` (str, optional): If provided, save figure to file
|
|
376
|
+
- `**kwargs`: Additional keyword arguments
|
|
377
|
+
|
|
378
|
+
**Returns:**
|
|
379
|
+
- `tuple`: (figure, axes)
|
|
380
|
+
|
|
381
|
+
## Requirements
|
|
382
|
+
|
|
383
|
+
- Python >= 3.7
|
|
384
|
+
- numpy >= 1.19.0
|
|
385
|
+
- scipy >= 1.5.0
|
|
386
|
+
- librosa >= 0.8.0
|
|
387
|
+
- matplotlib >= 3.3.0
|
|
388
|
+
|
|
389
|
+
## License
|
|
390
|
+
|
|
391
|
+
MIT License
|
|
392
|
+
|
|
393
|
+
## Versioning
|
|
394
|
+
|
|
395
|
+
This package uses [python-semantic-release](https://python-semantic-release.readthedocs.io/) for automatic version management based on [Conventional Commits](https://www.conventionalcommits.org/).
|
|
396
|
+
|
|
397
|
+
### How it works
|
|
398
|
+
|
|
399
|
+
The version is automatically determined from your commit messages:
|
|
400
|
+
- `fix:` or `fix(scope):` → patch version bump (0.0.1 → 0.0.2)
|
|
401
|
+
- `feat:` or `feat(scope):` → minor version bump (0.0.1 → 0.1.0)
|
|
402
|
+
- `feat!:` or `fix!:` or `BREAKING CHANGE:` → major version bump (0.0.1 → 1.0.0)
|
|
403
|
+
|
|
404
|
+
### Creating a new release
|
|
405
|
+
|
|
406
|
+
Simply push commits with conventional commit messages to the main branch:
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
git commit -m "feat: add new spectrogram visualization feature"
|
|
410
|
+
git push origin main
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
The GitHub Actions workflow will:
|
|
414
|
+
1. Analyze your commits since the last release
|
|
415
|
+
2. Determine the appropriate version bump
|
|
416
|
+
3. Update version numbers in `pyproject.toml` and `__init__.py`
|
|
417
|
+
4. Create a git tag
|
|
418
|
+
5. Generate/update CHANGELOG.md
|
|
419
|
+
6. Create a GitHub release
|
|
420
|
+
7. Build and publish to PyPI (if `PYPI_API_TOKEN` is configured)
|
|
421
|
+
|
|
422
|
+
### Commit message format
|
|
423
|
+
|
|
424
|
+
Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
425
|
+
|
|
426
|
+
```
|
|
427
|
+
<type>[optional scope]: <description>
|
|
428
|
+
|
|
429
|
+
[optional body]
|
|
430
|
+
|
|
431
|
+
[optional footer(s)]
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Types:**
|
|
435
|
+
- `feat`: A new feature
|
|
436
|
+
- `fix`: A bug fix
|
|
437
|
+
- `docs`: Documentation only changes
|
|
438
|
+
- `style`: Code style changes (formatting, etc.)
|
|
439
|
+
- `refactor`: Code refactoring
|
|
440
|
+
- `perf`: Performance improvements
|
|
441
|
+
- `test`: Adding or updating tests
|
|
442
|
+
- `chore`: Maintenance tasks
|
|
443
|
+
|
|
444
|
+
**Examples:**
|
|
445
|
+
```bash
|
|
446
|
+
git commit -m "feat: add support for custom color maps"
|
|
447
|
+
git commit -m "fix: correct frequency calculation in spectrogram"
|
|
448
|
+
git commit -m "feat!: change API for plot_spectrogram method"
|
|
449
|
+
git commit -m "docs: update installation instructions"
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Testing
|
|
453
|
+
|
|
454
|
+
Run tests using pytest:
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# Install development dependencies
|
|
458
|
+
pip install -e ".[dev]"
|
|
459
|
+
|
|
460
|
+
# Run all tests
|
|
461
|
+
pytest
|
|
462
|
+
|
|
463
|
+
# Run with verbose output
|
|
464
|
+
pytest -v
|
|
465
|
+
|
|
466
|
+
# Run specific test file
|
|
467
|
+
pytest tests/test_specplotter.py
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
The test suite includes:
|
|
471
|
+
- Unit tests for SpecPlotter initialization and configuration
|
|
472
|
+
- Tests for spectrogram computation
|
|
473
|
+
- Tests for plotting functionality
|
|
474
|
+
- Tests for CLI interface
|
|
475
|
+
- Tests for error handling
|
|
476
|
+
|
|
477
|
+
## Contributing
|
|
478
|
+
|
|
479
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
480
|
+
|
|
481
|
+
### Setting up pre-commit hooks
|
|
482
|
+
|
|
483
|
+
This project uses pre-commit hooks to ensure code quality. To set them up:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
# Install pre-commit
|
|
487
|
+
pip install pre-commit
|
|
488
|
+
|
|
489
|
+
# Install the git hooks
|
|
490
|
+
pre-commit install
|
|
491
|
+
|
|
492
|
+
# Or run manually
|
|
493
|
+
pre-commit run --all-files
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
The pre-commit hooks will automatically:
|
|
497
|
+
- Remove trailing whitespace
|
|
498
|
+
- Fix end-of-file issues
|
|
499
|
+
- Check YAML, JSON, and TOML syntax
|
|
500
|
+
- Format code with ruff
|
|
501
|
+
- Run ruff linting (with auto-fix)
|
|
502
|
+
- Check for merge conflicts
|
|
503
|
+
|
|
504
|
+
### Before submitting
|
|
505
|
+
|
|
506
|
+
1. Run the test suite: `pytest`
|
|
507
|
+
2. Run pre-commit hooks: `pre-commit run --all-files`
|
|
508
|
+
3. Ensure all tests pass
|
|
509
|
+
4. Ensure code formatting is correct
|