Skip to content

refactor: remove pyshtools and use ducc0 natively for SHT operations#112

Merged
mwyau merged 9 commits intomainfrom
feat/refactor-spectral-engine
Mar 25, 2026
Merged

refactor: remove pyshtools and use ducc0 natively for SHT operations#112
mwyau merged 9 commits intomainfrom
feat/refactor-spectral-engine

Conversation

@mwyau
Copy link
Owner

@mwyau mwyau commented Mar 25, 2026

Spectral Filter Parity vs. NCL (SPHEREPACK)

  • RMSE (Root Mean Square Error): Measures the square root of the average squared difference. It is sensitive to large outliers and expressed in the original units (Pa for MSL).
  • Absolute Error (Mean Absolute Error): The average of the absolute differences, providing a linear measure of typical deviation.
  • Relative Error: RMSE normalized by the mean absolute value of the reference field, indicating the error magnitude relative to the field strength.
  • Correlation: Pearson correlation coefficient, measuring the structural similarity between the filtered fields.
Case Engine RMSE Abs Err Rel Err Correlation
T5-42 shtns 0.45711949 0.16001313 0.000639669334 0.999999897272
ducc0 0.05266872 0.02130986 0.000073701880 0.999999998663
T0-42 shtns 0.45729947 0.16011983 0.000004525475 0.999999918845
ducc0 0.05369308 0.02328440 0.000000531351 0.999999998880

Benchmarks generated using benchmark/calculate_spectral_errors.py against ERA5 MSL test data.

Kinematics (Vorticity & Divergence) Parity vs. NCL

Vorticity and divergence are small-magnitude fields ($\sim 10^{-5} \text{ s}^{-1}$ for synoptic scales). The 11-16% relative error for shtns is primarily due to different default quadrature weights on regular grids (Fejer-like) compared to the Clenshaw-Curtis weights used by NCL/SPHEREPACK. ducc0 is configured to match NCL/SPHEREPACK exactly for these grids.

Reference Mean Absolute Values (ERA5 850hPa):

  • Vorticity: $1.696 \times 10^{-5} \text{ s}^{-1}$
  • Divergence: $1.648 \times 10^{-5} \text{ s}^{-1}$
Variable Engine RMSE Abs Err Rel Err Correlation
Vorticity shtns 0.00000188 0.00000116 0.111021616259 0.996666653748
ducc0 0.00000000 0.00000000 0.000000000000 1.000000000000
Divergence shtns 0.00000269 0.00000175 0.163410050750 0.993149458741
ducc0 0.00000000 0.00000000 0.000000000000 1.000000000000

Benchmarks generated using benchmark/calculate_vodv_errors.py against ERA5 UV test data.

Why shtns was removed from Kinematics

While shtns remains an excellent and high-precision engine for scalar transforms (as shown in the Spectral Filter benchmarks above), it has been removed as a backend for the kinematics (vorticity/divergence) module.

Exhaustive testing revealed that on regular latitude-longitude grids, shtns uses a different quadrature weighting scheme than NCL/SPHEREPACK. For vector-to-scalar transforms like $(u, v) \rightarrow (\zeta, \delta)$, this results in a persistent ~11-16% relative error compared to our reference baseline. In contrast, ducc0 provides a perfect bit-wise match ($RMSE=0.0$) and is now the sole engine for these calculations to ensure scientific integrity.

@codecov
Copy link

codecov bot commented Mar 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.57%. Comparing base (cecf0e1) to head (adb3819).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #112      +/-   ##
==========================================
- Coverage   62.82%   62.57%   -0.25%     
==========================================
  Files          25       25              
  Lines        2437     2357      -80     
==========================================
- Hits         1531     1475      -56     
+ Misses        906      882      -24     
Flag Coverage Δ
integration 54.94% <57.14%> (-0.05%) ⬇️
unit 58.59% <92.85%> (-0.30%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/pystormtracker/cli.py 81.70% <100.00%> (+0.11%) ⬆️
src/pystormtracker/hodges/tracker.py 80.67% <100.00%> (ø)
src/pystormtracker/models/tracker.py 100.00% <ø> (ø)
src/pystormtracker/preprocessing/kinematics.py 90.62% <100.00%> (+7.42%) ⬆️
src/pystormtracker/preprocessing/spectral.py 79.57% <100.00%> (+3.03%) ⬆️
src/pystormtracker/preprocessing/taper.py 23.80% <ø> (ø)
src/pystormtracker/simple/concurrent.py 53.94% <ø> (ø)
src/pystormtracker/simple/tracker.py 97.46% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mwyau mwyau marked this pull request as ready for review March 25, 2026 04:10
@mwyau mwyau merged commit 8bad852 into main Mar 25, 2026
14 checks passed
@mwyau mwyau deleted the feat/refactor-spectral-engine branch March 25, 2026 04:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant