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.
Files changed (40) hide show
  1. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/.gitignore +6 -0
  2. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/AGENTS.md +124 -52
  3. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/CHANGELOG.md +100 -17
  4. dct_toolkit-0.6.0/PKG-INFO +199 -0
  5. dct_toolkit-0.6.0/README.md +153 -0
  6. dct_toolkit-0.6.0/dct_toolkit/__init__.py +109 -0
  7. dct_toolkit-0.6.0/dct_toolkit/_kernels.py +31 -0
  8. dct_toolkit-0.6.0/dct_toolkit/_widths.py +34 -0
  9. dct_toolkit-0.6.0/dct_toolkit/cartesian.py +87 -0
  10. dct_toolkit-0.6.0/dct_toolkit/polar.py +295 -0
  11. dct_toolkit-0.6.0/dct_toolkit/stats.py +699 -0
  12. dct_toolkit-0.6.0/docs/API_REFERENCE.md +329 -0
  13. dct_toolkit-0.6.0/docs/MATHEMATICAL_BASIS.md +178 -0
  14. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/pyproject.toml +2 -2
  15. dct_toolkit-0.6.0/tests/test_api.py +84 -0
  16. dct_toolkit-0.6.0/tests/test_cartesian.py +195 -0
  17. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/tests/test_polar.py +38 -14
  18. dct_toolkit-0.6.0/tests/test_polar_kernels.py +244 -0
  19. dct_toolkit-0.6.0/tests/test_polar_robustness.py +157 -0
  20. dct_toolkit-0.6.0/tests/test_stats.py +687 -0
  21. dct_toolkit-0.6.0/tests/test_stats_nd.py +116 -0
  22. dct_toolkit-0.4.0/PKG-INFO +0 -161
  23. dct_toolkit-0.4.0/README.md +0 -115
  24. dct_toolkit-0.4.0/dct_toolkit/__init__.py +0 -63
  25. dct_toolkit-0.4.0/dct_toolkit/cartesian.py +0 -41
  26. dct_toolkit-0.4.0/dct_toolkit/polar.py +0 -264
  27. dct_toolkit-0.4.0/dct_toolkit/stats.py +0 -300
  28. dct_toolkit-0.4.0/docs/API_REFERENCE.md +0 -94
  29. dct_toolkit-0.4.0/docs/GAP_FILLING_BASIS.md +0 -166
  30. dct_toolkit-0.4.0/docs/MATHEMATICAL_BASIS.md +0 -77
  31. dct_toolkit-0.4.0/docs/PUBLICATION_GUIDE.md +0 -76
  32. dct_toolkit-0.4.0/tests/test_cartesian.py +0 -48
  33. dct_toolkit-0.4.0/tests/test_stats.py +0 -211
  34. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/LICENSE +0 -0
  35. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/dct_toolkit/core.py +0 -0
  36. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/dct_toolkit/gap_filling.py +0 -0
  37. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/examples/basic_polar.py +0 -0
  38. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/examples/comprehensive_demo.py +0 -0
  39. {dct_toolkit-0.4.0 → dct_toolkit-0.6.0}/tests/test_core.py +0 -0
  40. {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.4.0
5
- **Status**: Private Repository in Publication Preparation
6
- **Last Updated**: 2026-04-10
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 myenv
207
+ conda activate dct-publish
190
208
  ```
191
209
 
192
210
  2. **Verify Baseline**
193
211
  ```bash
194
- export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
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
- export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
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
- ### 🚧 In Progress: Publication Readiness (stats-first)
273
- - [x] Fix immediate correctness issues in core statistics path
274
- - [x] Create a dedicated publication-prep branch
275
- - [ ] Update `AGENTS.md` / docs to reflect publication plan and current state
276
- - [ ] Build clean public-facing scope focused on convolution/statistics
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
- - [ ] Define public API surface (exclude gap filling for initial public release)
282
- - [ ] Remove or relocate experimental assets from public-facing surface
283
- - [x] Add CI for tests and minimum quality checks
284
-
285
- ### 🔭 Future (post-public v1)
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
- export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
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
- ### Private Repository (Current)
353
- - Hosted on: GitHub (private)
354
- - Access: Core team only
355
- - Branching: feature branches → main
356
- - Manual testing required until CI is added
357
-
358
- ### Planned Public Release Scope
359
- - Initial public release is **convolution/statistics focused**
360
- - Keep DCT + periodic FFT boundary support in smoothing/statistical APIs
361
- - Defer gap-filling methods from initial public API surface
362
- - Add packaging metadata + license before publication
363
-
364
- ### Publication Assets (Current Branch)
365
- - `pyproject.toml` for pip builds and installation
366
- - `LICENSE` (MIT)
367
- - `.github/workflows/tests.yml` (pytest on push/PR)
368
- - `docs/PUBLICATION_GUIDE.md` with pip + conda-forge steps
369
- - `conda.recipe/meta.yaml` starter recipe for staged-recipes submission
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
- - **Core Test Report**: `exp_v3/TEST_REPORT_CORE.md`
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
- # Setup
399
- conda activate myenv
400
- export PYTHONPATH=$PYTHONPATH:$(pwd)/dct_toolkit
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
- # Test
403
- python -m pytest tests/ -v
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
- # Benchmark
409
- python exp_v3/test_width_impact.py
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
- ## [Unreleased]
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
- - **Packaging + distribution groundwork**:
12
- - Added `pyproject.toml` (PEP 517/518 via hatchling) for pip/wheel builds.
13
- - Added `LICENSE` (MIT).
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
- - `stats.py`: improved dtype handling for integer inputs in `dct_mean`/`dct_variance`
24
- with floating-point outputs and explicit mask-shape validation.
25
- - `README.md` and `docs/API_REFERENCE.md`: refocused public surface on
26
- convolution/statistics and documented `dct_prefill`.
27
- - `examples/comprehensive_demo.py`: removed stale experimental imports and aligned
28
- with stats-first public API.
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
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
50
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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`.