dct-toolkit 0.4.0__tar.gz → 0.6.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.
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/.gitignore +6 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/AGENTS.md +124 -52
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/CHANGELOG.md +100 -17
- dct_toolkit-0.6.0/PKG-INFO +199 -0
- dct_toolkit-0.6.0/README.md +153 -0
- dct_toolkit-0.6.0/dct_toolkit/__init__.py +109 -0
- dct_toolkit-0.6.0/dct_toolkit/_kernels.py +31 -0
- dct_toolkit-0.6.0/dct_toolkit/_widths.py +34 -0
- dct_toolkit-0.6.0/dct_toolkit/cartesian.py +87 -0
- dct_toolkit-0.6.0/dct_toolkit/polar.py +295 -0
- dct_toolkit-0.6.0/dct_toolkit/stats.py +699 -0
- dct_toolkit-0.6.0/docs/API_REFERENCE.md +329 -0
- dct_toolkit-0.6.0/docs/MATHEMATICAL_BASIS.md +178 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/pyproject.toml +2 -2
- dct_toolkit-0.6.0/tests/test_api.py +84 -0
- dct_toolkit-0.6.0/tests/test_cartesian.py +195 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/tests/test_polar.py +38 -14
- dct_toolkit-0.6.0/tests/test_polar_kernels.py +244 -0
- dct_toolkit-0.6.0/tests/test_polar_robustness.py +157 -0
- dct_toolkit-0.6.0/tests/test_stats.py +687 -0
- dct_toolkit-0.6.0/tests/test_stats_nd.py +116 -0
- dct_toolkit-0.4.0/PKG-INFO +0 -161
- dct_toolkit-0.4.0/README.md +0 -115
- dct_toolkit-0.4.0/dct_toolkit/__init__.py +0 -63
- dct_toolkit-0.4.0/dct_toolkit/cartesian.py +0 -41
- dct_toolkit-0.4.0/dct_toolkit/polar.py +0 -264
- dct_toolkit-0.4.0/dct_toolkit/stats.py +0 -300
- dct_toolkit-0.4.0/docs/API_REFERENCE.md +0 -94
- dct_toolkit-0.4.0/docs/GAP_FILLING_BASIS.md +0 -166
- dct_toolkit-0.4.0/docs/MATHEMATICAL_BASIS.md +0 -77
- dct_toolkit-0.4.0/docs/PUBLICATION_GUIDE.md +0 -76
- dct_toolkit-0.4.0/tests/test_cartesian.py +0 -48
- dct_toolkit-0.4.0/tests/test_stats.py +0 -211
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/LICENSE +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/dct_toolkit/core.py +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/dct_toolkit/gap_filling.py +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/examples/basic_polar.py +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/examples/comprehensive_demo.py +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/tests/test_core.py +0 -0
- {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/tests/test_gap_filling.py +0 -0
|
@@ -40,6 +40,7 @@ Thumbs.db
|
|
|
40
40
|
# Jupyter
|
|
41
41
|
.ipynb_checkpoints/
|
|
42
42
|
*.ipynb
|
|
43
|
+
!notebooks/*.ipynb
|
|
43
44
|
|
|
44
45
|
# Environment
|
|
45
46
|
.env
|
|
@@ -56,3 +57,8 @@ site/
|
|
|
56
57
|
.mypy_cache/
|
|
57
58
|
.dmypy.json
|
|
58
59
|
dmypy.json
|
|
60
|
+
|
|
61
|
+
# Local scratch / reference scripts
|
|
62
|
+
.opencode/
|
|
63
|
+
get_radar_smoothing.py
|
|
64
|
+
radar_smoothing_ref.py
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# AGENTS.md - DCT Toolkit Agent Guidelines
|
|
2
2
|
|
|
3
3
|
**Project**: dct-toolkit
|
|
4
|
-
**Version**: 0.
|
|
5
|
-
**Status**:
|
|
6
|
-
**Last Updated**: 2026-
|
|
4
|
+
**Version**: 0.6.0
|
|
5
|
+
**Status**: Preparing v0.6.0 release (PyPI & conda-forge)
|
|
6
|
+
**Last Updated**: 2026-09-21
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -34,6 +34,19 @@ conda activate myenv
|
|
|
34
34
|
python --version # Should be 3.8+
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
### dct-publish Environment (Publication & Development)
|
|
38
|
+
Pre-configured environment for publication, testing, and notebook development:
|
|
39
|
+
```bash
|
|
40
|
+
conda activate dct-publish
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Packages installed:**
|
|
44
|
+
- Python 3.11, numpy, scipy, pytest
|
|
45
|
+
- xarray, matplotlib, cmweather (radar colormaps)
|
|
46
|
+
- open-radar-data (sample radar datasets)
|
|
47
|
+
- build, twine (for PyPI publishing)
|
|
48
|
+
- dct-toolkit v0.5.0 (editable install)
|
|
49
|
+
|
|
37
50
|
### PYTHONPATH
|
|
38
51
|
When running tests or examples from project root:
|
|
39
52
|
```bash
|
|
@@ -65,6 +78,8 @@ conda deactivate
|
|
|
65
78
|
|
|
66
79
|
**Why isolated?** Building tools (`build`, `twine`) and their dependencies can conflict with other packages in your base environment (e.g., Sphinx, Streamlit). Always use an isolated environment for package operations.
|
|
67
80
|
|
|
81
|
+
**Note:** The `dct-publish` environment is pre-configured for development, testing, and notebook work. Use it for day-to-day development. Create a fresh isolated environment only when you need to build/publish to PyPI.
|
|
82
|
+
|
|
68
83
|
---
|
|
69
84
|
|
|
70
85
|
## Code Style - Scientific Repository Standards
|
|
@@ -159,6 +174,9 @@ dct_toolkit/ # PROJECT ROOT
|
|
|
159
174
|
│ ├── basic_polar.py
|
|
160
175
|
│ └── comprehensive_demo.py
|
|
161
176
|
│
|
|
177
|
+
├── notebooks/ # JUPYTER NOTEBOOKS
|
|
178
|
+
│ └── 01_getting_started.ipynb
|
|
179
|
+
│
|
|
162
180
|
├── exp_v3/ # EXPERIMENTS (reports + code)
|
|
163
181
|
│ ├── figures/ # Generated figures (PNG/PDF)
|
|
164
182
|
│ ├── test_width_impact.py
|
|
@@ -186,13 +204,12 @@ dct_toolkit/ # PROJECT ROOT
|
|
|
186
204
|
|
|
187
205
|
1. **Activate Environment**
|
|
188
206
|
```bash
|
|
189
|
-
conda activate
|
|
207
|
+
conda activate dct-publish
|
|
190
208
|
```
|
|
191
209
|
|
|
192
210
|
2. **Verify Baseline**
|
|
193
211
|
```bash
|
|
194
|
-
|
|
195
|
-
python -m pytest tests/ -v
|
|
212
|
+
python -m pytest /path/to/dct_toolkit/tests/ -v
|
|
196
213
|
```
|
|
197
214
|
All tests in `tests/` must pass before you start.
|
|
198
215
|
|
|
@@ -222,8 +239,8 @@ dct_toolkit/ # PROJECT ROOT
|
|
|
222
239
|
|
|
223
240
|
**Run Tests**:
|
|
224
241
|
```bash
|
|
225
|
-
|
|
226
|
-
python -m pytest tests/ -v
|
|
242
|
+
conda activate dct-publish
|
|
243
|
+
python -m pytest /path/to/dct_toolkit/tests/ -v
|
|
227
244
|
```
|
|
228
245
|
|
|
229
246
|
**Expected Output**: all tests passing
|
|
@@ -269,25 +286,27 @@ Before declaring task complete:
|
|
|
269
286
|
- [x] Test suite (`tests/`) passing
|
|
270
287
|
- [x] Documentation suite
|
|
271
288
|
|
|
272
|
-
###
|
|
273
|
-
- [x] Fix immediate correctness issues in core statistics path
|
|
274
|
-
- [x] Create
|
|
275
|
-
- [
|
|
276
|
-
- [
|
|
277
|
-
|
|
278
|
-
### 📋 Before Public Release
|
|
289
|
+
### ✅ Completed (Publication Readiness)
|
|
290
|
+
- [x] Fix immediate correctness issues in core statistics path (integer dtype bug)
|
|
291
|
+
- [x] Create dedicated publication-prep branches
|
|
292
|
+
- [x] Update `AGENTS.md` / docs to reflect publication plan
|
|
293
|
+
- [x] Build clean public-facing scope focused on convolution/statistics
|
|
279
294
|
- [x] Add packaging metadata (`pyproject.toml`)
|
|
280
|
-
- [x] Add `LICENSE` and align README badges/claims
|
|
281
|
-
- [
|
|
282
|
-
- [
|
|
283
|
-
- [x] Add CI for tests
|
|
284
|
-
|
|
285
|
-
|
|
295
|
+
- [x] Add `LICENSE` (MIT) and align README badges/claims
|
|
296
|
+
- [x] Define public API surface (exclude gap filling for initial public release)
|
|
297
|
+
- [x] Remove experimental assets from public-facing surface
|
|
298
|
+
- [x] Add CI for tests (`.github/workflows/tests.yml`)
|
|
299
|
+
- [x] Publish to PyPI (v0.4.0 live at https://pypi.org/project/dct-toolkit/)
|
|
300
|
+
- [x] Submit conda-forge recipe (PR #32930 in review)
|
|
301
|
+
- [x] Merge publication work to `main` branch
|
|
302
|
+
- [x] Tag `v0.4.0` release
|
|
303
|
+
- [x] Create `research/gap-filling` branch for long-term research
|
|
304
|
+
|
|
305
|
+
### 🔭 Future (v0.5.0 and beyond)
|
|
286
306
|
- [ ] 3D support (volumetric data)
|
|
287
307
|
- [ ] Additional kernels (Savitzky-Golay, Hanning)
|
|
288
308
|
- [ ] Performance optimizations (numba?)
|
|
289
309
|
- [ ] Jupyter notebook examples
|
|
290
|
-
- [ ] conda-forge distribution
|
|
291
310
|
- [ ] Advanced gap filling (constrained optimization)
|
|
292
311
|
- [ ] GPU acceleration (CuPy)
|
|
293
312
|
|
|
@@ -326,7 +345,7 @@ Formula for robust mean with gaps:
|
|
|
326
345
|
**Problem**: `ModuleNotFoundError: No module named 'dct_toolkit'`
|
|
327
346
|
**Solution**:
|
|
328
347
|
```bash
|
|
329
|
-
|
|
348
|
+
conda activate dct-publish
|
|
330
349
|
```
|
|
331
350
|
|
|
332
351
|
### 2. Path Confusion
|
|
@@ -349,24 +368,69 @@ export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
|
|
|
349
368
|
|
|
350
369
|
## Repository Management
|
|
351
370
|
|
|
352
|
-
###
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
- `
|
|
366
|
-
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
-
|
|
371
|
+
### Branch Strategy
|
|
372
|
+
|
|
373
|
+
We use a **trunk-based workflow** with dedicated branches for different purposes:
|
|
374
|
+
|
|
375
|
+
| Branch | Purpose | Stability |
|
|
376
|
+
|--------|---------|-----------|
|
|
377
|
+
| `main` | Public releases, stable code | **Production-ready** |
|
|
378
|
+
| `research/gap-filling` | Long-term gap-filling research | Experimental |
|
|
379
|
+
| `feature/*` | Short-lived feature development | In-progress |
|
|
380
|
+
|
|
381
|
+
#### `main` Branch (The Public Package)
|
|
382
|
+
- Always matches the latest PyPI release
|
|
383
|
+
- Contains only public API: core, cartesian, polar, stats
|
|
384
|
+
- Gap-filling code exists in `gap_filling.py` but is **not exported** in `__init__.py`
|
|
385
|
+
- All tests must pass before merging
|
|
386
|
+
|
|
387
|
+
#### `research/gap-filling` Branch
|
|
388
|
+
- Dedicated branch for long-term gap-filling research
|
|
389
|
+
- Safe to experiment with `dct_inpaint`, `iterative_gap_fill`
|
|
390
|
+
- Regularly merge `main` into this branch to get bug fixes and new features
|
|
391
|
+
- Not merged back to `main` until research matures
|
|
392
|
+
|
|
393
|
+
**To sync research branch with latest main:**
|
|
394
|
+
```bash
|
|
395
|
+
git checkout research/gap-filling
|
|
396
|
+
git merge main
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Feature Branches
|
|
400
|
+
For new development (Hanning window, 3D support, notebooks):
|
|
401
|
+
```bash
|
|
402
|
+
# Create feature branch from main
|
|
403
|
+
git checkout main
|
|
404
|
+
git checkout -b feature/hanning-window
|
|
405
|
+
|
|
406
|
+
# Work, commit, push
|
|
407
|
+
git push origin feature/hanning-window
|
|
408
|
+
|
|
409
|
+
# When done, merge to main via PR
|
|
410
|
+
git checkout main
|
|
411
|
+
git merge feature/hanning-window
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Repository Status
|
|
415
|
+
- GitHub: Private (core team access only)
|
|
416
|
+
- PyPI: **Public** — `pip install dct-toolkit` works
|
|
417
|
+
- conda-forge: **Submitted** — PR #32930 in review at `conda-forge/staged-recipes`
|
|
418
|
+
|
|
419
|
+
**Check conda-forge PR Status**:
|
|
420
|
+
```bash
|
|
421
|
+
gh pr view 32930 --repo conda-forge/staged-recipes
|
|
422
|
+
# Or visit: https://github.com/conda-forge/staged-recipes/pull/32930
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Current Version
|
|
426
|
+
- `v0.6.0` — Support for anisotropic smoothing widths, per-axis Cartesian kernels,
|
|
427
|
+
mixed polar kernels, periodic polar prefill, and effective density gating.
|
|
428
|
+
- Tag: `git checkout v0.6.0`
|
|
429
|
+
|
|
430
|
+
### Gap-Filling Status
|
|
431
|
+
- Code exists in `dct_toolkit/gap_filling.py` (available for import directly)
|
|
432
|
+
- **Not exported** in public API (`__init__.py`) — research-internal
|
|
433
|
+
- Full gap-filling to be released in future v1.x after research matures
|
|
370
434
|
|
|
371
435
|
---
|
|
372
436
|
|
|
@@ -374,15 +438,13 @@ export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
|
|
|
374
438
|
|
|
375
439
|
### Documentation
|
|
376
440
|
- **Math Theory**: `docs/MATHEMATICAL_BASIS.md`
|
|
377
|
-
- **Gap Filling Basis**: `docs/GAP_FILLING_BASIS.md`
|
|
378
441
|
- **API Details**: `docs/API_REFERENCE.md`
|
|
379
|
-
- **
|
|
380
|
-
- **Gap Filling Report**: `exp_v3/TEST_REPORT_GAP_FILLING.md`
|
|
442
|
+
- **Getting Started**: `notebooks/01_getting_started.ipynb`
|
|
381
443
|
|
|
382
444
|
### Code Examples
|
|
445
|
+
- **Getting Started Notebook**: `notebooks/01_getting_started.ipynb`
|
|
383
446
|
- **Polar Smoothing**: `examples/basic_polar.py`
|
|
384
447
|
- **Full Demo**: `examples/comprehensive_demo.py`
|
|
385
|
-
- **Gap Filling**: `exp_v3/test_width_impact.py`
|
|
386
448
|
|
|
387
449
|
### Key Papers & References
|
|
388
450
|
- Garcia (2010): DCT-PLS (contrast/background)
|
|
@@ -395,18 +457,28 @@ export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
|
|
|
395
457
|
## Quick Reference Card
|
|
396
458
|
|
|
397
459
|
```bash
|
|
398
|
-
#
|
|
399
|
-
|
|
400
|
-
|
|
460
|
+
# Install (pip)
|
|
461
|
+
pip install dct-toolkit
|
|
462
|
+
|
|
463
|
+
# Install (conda - once feed stock is merged)
|
|
464
|
+
conda install -c conda-forge dct-toolkit
|
|
465
|
+
|
|
466
|
+
# Development install from source
|
|
467
|
+
git clone https://github.com/JValdivia23/dct-toolkit.git
|
|
468
|
+
cd dct-toolkit
|
|
469
|
+
pip install -e .
|
|
470
|
+
|
|
471
|
+
# Activate dct-publish environment (for testing/notebooks)
|
|
472
|
+
conda activate dct-publish
|
|
401
473
|
|
|
402
|
-
#
|
|
403
|
-
python -m pytest tests
|
|
474
|
+
# Run tests (from project root)
|
|
475
|
+
python -m pytest tests -v
|
|
404
476
|
|
|
405
477
|
# Run example
|
|
406
478
|
python examples/basic_polar.py
|
|
407
479
|
|
|
408
|
-
#
|
|
409
|
-
|
|
480
|
+
# Open Jupyter notebook
|
|
481
|
+
jupyter notebook notebooks/01_getting_started.ipynb
|
|
410
482
|
|
|
411
483
|
# Check imports (should be empty)
|
|
412
484
|
grep -r "^from \.\./" dct_toolkit/dct_toolkit/
|
|
@@ -5,27 +5,110 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.6.0] - 2026-09-21
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Added anisotropic width support while keeping scalar width as the default path:
|
|
12
|
+
- Cartesian smoothing/stats now accept `width` as scalar or length-`ndim` sequence.
|
|
13
|
+
- Polar smoothing/stats now accept `width` as scalar or
|
|
14
|
+
`(width_azimuth, width_range)`.
|
|
15
|
+
- `dct_count` now uses anisotropic window area (`prod(widths)` in Cartesian,
|
|
16
|
+
`width_range * width_azimuth/(r*dtheta)` in polar).
|
|
17
|
+
- `dct_prefill` now gates per-iteration mean estimates by the local valid-sample
|
|
18
|
+
density (`smooth(mask)`) with `min_effective_density=0.35` by default. This
|
|
19
|
+
stabilizes iterative gap-filling in low-support regions and uses the same
|
|
20
|
+
density signal that `dct_count / area` represents internally. The gate is
|
|
21
|
+
applied uniformly across Cartesian and polar coordinates and can be disabled
|
|
22
|
+
by passing `min_effective_density=None`.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Added mixed polar kernels in `(azimuth, range)` order for `smooth_polar`,
|
|
26
|
+
both polar transfer-function entry points, and high-level smoothing,
|
|
27
|
+
statistics, and prefill. A single string still applies to both dimensions.
|
|
28
|
+
Both azimuth boundary modes retain range-adaptive widths and apply azimuth
|
|
29
|
+
smoothing before reflective range smoothing.
|
|
30
|
+
- Added independent polar reference tests covering all mixed kernel pairs,
|
|
31
|
+
circular discrete averaging, odd/even azimuth lengths, singleton axes,
|
|
32
|
+
input validation, normalized statistics, prefill, and NaN handling.
|
|
33
|
+
- Added per-axis Cartesian kernel types: `kernel_type` accepts a string or a
|
|
34
|
+
length-`ndim` sequence of `'boxcar'`, `'boxcar_discrete'`, and `'gaussian'`.
|
|
35
|
+
Mixed kernels work with scalar/per-axis widths in `smooth_cartesian`,
|
|
36
|
+
`dct_smooth`, and Cartesian statistics/prefill. Existing single-string calls
|
|
37
|
+
retain their behavior; the backend still uses one forward/inverse N-D DCT pair.
|
|
38
|
+
- Added mixed-kernel reference, validation, and NaN-handling tests, plus a 3D
|
|
39
|
+
usage example and documentation of array axis order and Gaussian width units.
|
|
40
|
+
- Added parity and artifact-regression tests for scalar-vs-vector isotropic widths,
|
|
41
|
+
plus anisotropic Cartesian/polar smoke coverage.
|
|
42
|
+
- Added `min_effective_density` keyword argument to `dct_prefill` (default
|
|
43
|
+
`0.35`) and `dct_mean` (default `None`, opt-in) for count-based stability
|
|
44
|
+
gating. When set, `dct_mean` returns NaN wherever the local valid-sample
|
|
45
|
+
density is below the threshold. New tests in `tests/test_stats.py` cover
|
|
46
|
+
the default, the disabled, the custom threshold, and the polar-coordinates
|
|
47
|
+
paths.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
- Polar nearest-neighbor prefill now respects periodic azimuth in both axis-wise
|
|
51
|
+
propagation and the global fallback, correcting seam-dependent results on
|
|
52
|
+
sparse sweeps. Range propagation remains nonperiodic. Added sparse-sweep
|
|
53
|
+
rotation, targeted global fallback, and singleton-axis regression tests.
|
|
54
|
+
- Polar smoothing, statistics, and prefill now require a finite, positive real
|
|
55
|
+
scalar `az_res_deg`, including calls that return early without smoothing.
|
|
56
|
+
Shared spacing validation prevents negative counts and invalid width arithmetic;
|
|
57
|
+
tests cover invalid inputs and valid fractional/NumPy scalar spacings.
|
|
58
|
+
- Periodic azimuth with `'boxcar_discrete'` now uses an actual centered discrete
|
|
59
|
+
boxcar with an odd integer window, matching the reflective width convention.
|
|
60
|
+
It previously substituted a Gaussian, so results for this option intentionally
|
|
61
|
+
change for both single-string and mixed-kernel calls.
|
|
62
|
+
|
|
63
|
+
## [0.5.0] - 2026-04-14
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
- `smooth_cartesian` now uses a single N-D spectral pass (`dctn/idctn`) with
|
|
67
|
+
broadcasted separable transfer functions, preserving output equivalence while
|
|
68
|
+
reducing transform overhead for higher-dimensional Cartesian arrays.
|
|
69
|
+
- Default smoothing kernel is now `'gaussian'` for Cartesian and polar smoothing paths
|
|
70
|
+
(`smooth_cartesian`, `smooth_polar`, and all wrapper/statistics calls that inherit
|
|
71
|
+
those defaults).
|
|
72
|
+
- `dct_smooth` now enforces a NaN-safe smoothing pipeline: if NaNs are present, it
|
|
73
|
+
automatically pre-fills missing values before spectral smoothing and restores the
|
|
74
|
+
original NaN mask afterward.
|
|
75
|
+
- `dct_prefill` now applies mandatory nearest-neighbor residual fill for unresolved
|
|
76
|
+
targets, guaranteeing finite arrays for downstream spectral smoothing when support
|
|
77
|
+
exists.
|
|
78
|
+
- Default prefill iteration count is now `max_iter=3` for predictable runtime. You can
|
|
79
|
+
still set `max_iter=None` to iterate until convergence (safety cap: 20).
|
|
80
|
+
- `dct_mean`, `dct_variance`, and `dct_std` now include stable fallback handling for
|
|
81
|
+
poorly conditioned normalized-convolution regions (heavy-gap volumes), preventing
|
|
82
|
+
NaN/overflow behavior in low-support areas when valid support exists.
|
|
83
|
+
- `dct_count` now clips smoothed density to `[0, 1]` before area scaling to keep
|
|
84
|
+
effective sample counts physically valid.
|
|
85
|
+
- `dct_count`, `dct_mean`, `dct_variance`, and `dct_std` now default to
|
|
86
|
+
`restore_input_nan=True`, masking outputs at original invalid locations while
|
|
87
|
+
keeping valid locations stable and finite.
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
- Added NaN-policy regression tests for `dct_smooth` and new `dct_prefill` iteration/
|
|
91
|
+
residual behavior (`tests/test_api.py`, updates in `tests/test_stats.py`).
|
|
92
|
+
- Added Cartesian N-D equivalence tests to verify artifact-free 3D/4D outputs and
|
|
93
|
+
new N-D statistics smoke tests (`tests/test_cartesian.py`, `tests/test_stats_nd.py`).
|
|
94
|
+
|
|
95
|
+
## [0.4.1] - 2026-04-12
|
|
9
96
|
|
|
10
97
|
### Added
|
|
11
|
-
- **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- Added GitHub Actions CI workflow `.github/workflows/tests.yml`.
|
|
15
|
-
- Added `docs/PUBLICATION_GUIDE.md` with PyPI + conda-forge release steps.
|
|
16
|
-
- Added `conda.recipe/meta.yaml` starter recipe for conda-forge submission prep.
|
|
17
|
-
- **Statistics API**:
|
|
18
|
-
- Added `dct_prefill` (iterative normalized-convolution prefill) and exported it
|
|
19
|
-
in the top-level API.
|
|
20
|
-
- Added regression tests for `dct_prefill` behavior and parameter validation.
|
|
98
|
+
- **Jupyter Notebook**: Added `notebooks/01_getting_started.ipynb` with interactive
|
|
99
|
+
tutorial for DCT smoothing and statistics.
|
|
100
|
+
- Updated `.gitignore` to allow notebooks in `notebooks/` folder.
|
|
21
101
|
|
|
22
102
|
### Changed
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
- `
|
|
26
|
-
|
|
27
|
-
- `
|
|
28
|
-
|
|
103
|
+
- **Repository Cleanup**: Moved experimental content to `research/gap-filling` branch:
|
|
104
|
+
- Removed `exp_v3/` and `exp_v4/` experimental folders from main branch.
|
|
105
|
+
- Removed `docs/GAP_FILLING_BASIS.md` and `docs/PUBLICATION_GUIDE.md` from main branch.
|
|
106
|
+
- `gap_filling.py` remains in codebase but is **not exported** in public API.
|
|
107
|
+
- `__init__.py`: Version bumped to `0.4.1`.
|
|
108
|
+
|
|
109
|
+
### Notes
|
|
110
|
+
- Main branch now contains only core package functionality for stable PyPI releases.
|
|
111
|
+
- All experimental work (gap filling, inpainting) preserved in `research/gap-filling` branch.
|
|
29
112
|
|
|
30
113
|
## [0.4.0] - 2026-02-28
|
|
31
114
|
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dct-toolkit
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: DCT/FFT-based convolutional statistics for Cartesian and polar data
|
|
5
|
+
Author-email: "Jairo M. Valdivia" <Jairo.ValdiviaPrado@colorado.edu>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Jairo M. Valdivia
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Keywords: convolution,dct,fft,polar,radar,smoothing,statistics
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: Intended Audience :: Science/Research
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Topic :: Scientific/Engineering
|
|
41
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
42
|
+
Requires-Python: >=3.8
|
|
43
|
+
Requires-Dist: numpy>=1.20
|
|
44
|
+
Requires-Dist: scipy>=1.8
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# DCT-Toolkit: Convolutional Statistics
|
|
48
|
+
|
|
49
|
+
[](https://www.python.org/downloads/)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
|
|
52
|
+
`dct_toolkit` provides DCT-based smoothing and normalized-convolution statistics for
|
|
53
|
+
data with gaps. The current publication-prep track is intentionally focused on the
|
|
54
|
+
convolution/statistics surface.
|
|
55
|
+
|
|
56
|
+
## Current Scope (Stats-First)
|
|
57
|
+
|
|
58
|
+
- DCT-based smoothing for 1D/N-D Cartesian data.
|
|
59
|
+
- Per-axis Cartesian widths and kernel types, including mixed boxcar/Gaussian smoothing.
|
|
60
|
+
- Polar smoothing with adaptive azimuth widths and independent azimuth/range kernel types.
|
|
61
|
+
- Reflective boundaries via DCT and periodic azimuth boundaries via real FFT.
|
|
62
|
+
- Robust local statistics (`dct_mean`, `dct_variance`, `dct_std`, `dct_count`) with NaN support.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
### pip
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install dct-toolkit
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### conda (pending conda-forge approval)
|
|
73
|
+
|
|
74
|
+
Conda-forge packaging has been submitted (PR under review). This option would be available soon:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
conda install dct-toolkit
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### 1) Robust Mean with Missing Data
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import numpy as np
|
|
86
|
+
import dct_toolkit as dct
|
|
87
|
+
|
|
88
|
+
data = np.sin(np.linspace(0, 10, 200))
|
|
89
|
+
data[70:110] = np.nan
|
|
90
|
+
|
|
91
|
+
mu = dct.dct_mean(data, width=10.0)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 1b) Prefill Before Full-Field Smoothing
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
smoothed = dct.dct_smooth(prefilled, width=10.0)
|
|
98
|
+
```
|
|
99
|
+
This function will call `dct.dct_prefill()` internally. We need to fill NaNs as requirement for DCT or FFT operations by default.
|
|
100
|
+
|
|
101
|
+
### 2) Polar Smoothing with Periodic Azimuth
|
|
102
|
+
|
|
103
|
+
For data in **(azimuth, range)** order, combine a boxcar along azimuth with a
|
|
104
|
+
Gaussian along range:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
smoothed = dct.dct_smooth(
|
|
108
|
+
radar_data,
|
|
109
|
+
width=(5.0, 3.0),
|
|
110
|
+
coordinates="polar",
|
|
111
|
+
kernel_type=("boxcar", "gaussian"),
|
|
112
|
+
az_boundary="periodic",
|
|
113
|
+
az_res_deg=1.0,
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Both sequences follow `(azimuth, range)` order. Azimuth width adapts with range:
|
|
118
|
+
`width_azimuth / (r * dtheta)` beams, where `r` starts at 1 and `dtheta` is the
|
|
119
|
+
azimuth spacing in radians. Range width is in range gates. Gaussian
|
|
120
|
+
`sigma = effective_width / sqrt(12)` on the selected axis. Filtering applies
|
|
121
|
+
azimuth first, then range; both periodic and reflective azimuth support all
|
|
122
|
+
three kernel types, including `'boxcar_discrete'`.
|
|
123
|
+
`az_res_deg` must be a finite, positive scalar in degrees. For gapped data,
|
|
124
|
+
periodic azimuth also wraps the nearest-neighbor prefill fallback across the
|
|
125
|
+
sweep seam; range distances remain nonperiodic.
|
|
126
|
+
|
|
127
|
+
### 3) Local Variability Estimates
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
var = dct.dct_variance(data, width=10.0)
|
|
131
|
+
std = dct.dct_std(data, width=10.0)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 4) Mixed Kernels for a 3D Volume
|
|
135
|
+
|
|
136
|
+
For a volume stored in **(z, y, x)** order, apply Gaussian smoothing vertically
|
|
137
|
+
and boxcar smoothing horizontally:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
rng = np.random.default_rng(42)
|
|
141
|
+
volume = rng.standard_normal((16, 32, 32)) # (z, y, x)
|
|
142
|
+
|
|
143
|
+
smoothed = dct.dct_smooth(
|
|
144
|
+
volume,
|
|
145
|
+
width=(3.0, 5.0, 5.0),
|
|
146
|
+
kernel_type=("gaussian", "boxcar", "boxcar"),
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# The same kernels work with normalized statistics on data containing NaNs.
|
|
150
|
+
volume[5:7, 12:15, 12:15] = np.nan
|
|
151
|
+
mean = dct.dct_mean(
|
|
152
|
+
volume,
|
|
153
|
+
width=(3.0, 5.0, 5.0),
|
|
154
|
+
kernel_type=("gaussian", "boxcar", "boxcar"),
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Kernel and width sequences follow NumPy axis order and must have one entry per
|
|
159
|
+
dimension. Widths are in grid cells along each axis; Gaussian
|
|
160
|
+
`sigma = width / sqrt(12)`. Convert physical widths using the corresponding
|
|
161
|
+
grid spacing before calling. A scalar width applies equal widths, and a single
|
|
162
|
+
kernel string applies that kernel to every axis. Equal widths with different
|
|
163
|
+
kernel types can still produce anisotropic smoothing. Polar smoothing also
|
|
164
|
+
accepts a kernel pair, using the `(azimuth, range)` convention shown above.
|
|
165
|
+
|
|
166
|
+
## Quick Cheat Sheet
|
|
167
|
+
|
|
168
|
+
| Function | Description |
|
|
169
|
+
|----------|-------------|
|
|
170
|
+
| `get_dct_transfer_function` | Build 1D spectral kernel `H[k]` from width and kernel type. |
|
|
171
|
+
| `dct_convolve_1d` | Apply one 1D DCT convolution along one axis using a precomputed `H`. |
|
|
172
|
+
| `smooth_cartesian` | Low-level separable smoothing for N-D Cartesian arrays. |
|
|
173
|
+
| `smooth_polar` | Low-level smoothing for 2D polar arrays with adaptive azimuth width. |
|
|
174
|
+
| `dct_smooth` | Top-level "just smooth this" wrapper (auto-pre-fills NaNs, then restores NaN mask). |
|
|
175
|
+
| `dct_mean` | NaN-robust local mean via normalized convolution. |
|
|
176
|
+
| `dct_count` | Effective local sample count from a validity mask. |
|
|
177
|
+
| `dct_prefill` | Iterative normalized-convolution gap fill (often used before full-field smoothing). |
|
|
178
|
+
| `dct_variance` | NaN-robust local variance from normalized-convolution moments. |
|
|
179
|
+
| `dct_std` | NaN-robust local standard deviation (`sqrt(dct_variance)`). |
|
|
180
|
+
|
|
181
|
+
## Pre-filling (`dct_prefill`)
|
|
182
|
+
|
|
183
|
+
`dct_prefill` provides an **iterative normalized-convolution gap fill** based on `dct_mean`:
|
|
184
|
+
|
|
185
|
+
- Fills gaps (NaNs or a specified mask) using iterative local averaging.
|
|
186
|
+
- Preserves non-target values exactly.
|
|
187
|
+
- Intended as a **pre-processing step** before full-field smoothing.
|
|
188
|
+
- `max_iter=3` by default for predictable runtime; use `max_iter=None` to iterate until convergence (all NaNs filled). By default, any remaining NaNs are filled with the nearest valid data.
|
|
189
|
+
|
|
190
|
+
See the Quick Start section above for usage examples.
|
|
191
|
+
|
|
192
|
+
## Documentation
|
|
193
|
+
|
|
194
|
+
- `docs/MATHEMATICAL_BASIS.md` — Mathematical foundations and theory
|
|
195
|
+
- `docs/API_REFERENCE.md` — Complete API documentation
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT. See `LICENSE`.
|