dct-toolkit 0.4.0__py3-none-any.whl
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/__init__.py +63 -0
- dct_toolkit/cartesian.py +41 -0
- dct_toolkit/core.py +123 -0
- dct_toolkit/gap_filling.py +815 -0
- dct_toolkit/polar.py +264 -0
- dct_toolkit/stats.py +300 -0
- dct_toolkit-0.4.0.dist-info/METADATA +161 -0
- dct_toolkit-0.4.0.dist-info/RECORD +10 -0
- dct_toolkit-0.4.0.dist-info/WHEEL +4 -0
- dct_toolkit-0.4.0.dist-info/licenses/LICENSE +21 -0
dct_toolkit/__init__.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Public API for DCT-based convolution and statistical operations.
|
|
2
|
+
|
|
3
|
+
The public top-level surface is intentionally scoped to smoothing and
|
|
4
|
+
normalized-convolution statistics for the publication-focused release track.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from .core import dct_convolve_1d, get_dct_transfer_function
|
|
12
|
+
from .cartesian import smooth_cartesian
|
|
13
|
+
from .polar import smooth_polar
|
|
14
|
+
from .stats import dct_count, dct_mean, dct_prefill, dct_std, dct_variance
|
|
15
|
+
|
|
16
|
+
__version__ = "0.4.0"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"__version__",
|
|
21
|
+
"get_dct_transfer_function",
|
|
22
|
+
"dct_convolve_1d",
|
|
23
|
+
"smooth_cartesian",
|
|
24
|
+
"smooth_polar",
|
|
25
|
+
"dct_smooth",
|
|
26
|
+
"dct_count",
|
|
27
|
+
"dct_mean",
|
|
28
|
+
"dct_prefill",
|
|
29
|
+
"dct_variance",
|
|
30
|
+
"dct_std",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def dct_smooth(
|
|
35
|
+
data: np.ndarray,
|
|
36
|
+
width: float,
|
|
37
|
+
coordinates: str = "cartesian",
|
|
38
|
+
**kwargs: Any,
|
|
39
|
+
) -> np.ndarray:
|
|
40
|
+
"""
|
|
41
|
+
Apply DCT-based smoothing.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
data : np.ndarray
|
|
46
|
+
Input data.
|
|
47
|
+
width : float
|
|
48
|
+
Smoothing width.
|
|
49
|
+
coordinates : str, default='cartesian'
|
|
50
|
+
'cartesian' or 'polar'.
|
|
51
|
+
**kwargs
|
|
52
|
+
Additional arguments (kernel_type, az_res_deg, etc.)
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
smoothed : np.ndarray
|
|
57
|
+
Smoothed data.
|
|
58
|
+
"""
|
|
59
|
+
if coordinates == "cartesian":
|
|
60
|
+
return smooth_cartesian(data, width, **kwargs)
|
|
61
|
+
if coordinates == "polar":
|
|
62
|
+
return smooth_polar(data, width_pixels=width, **kwargs)
|
|
63
|
+
raise ValueError(f"Unknown coordinates: {coordinates}")
|
dct_toolkit/cartesian.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
2D Cartesian Smoothing.
|
|
3
|
+
|
|
4
|
+
This module provides separable smoothing for N-D Cartesian data.
|
|
5
|
+
It applies 1D smoothing sequentially along each dimension.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from .core import get_dct_transfer_function, dct_convolve_1d
|
|
10
|
+
|
|
11
|
+
def smooth_cartesian(data: np.ndarray, width: float, kernel_type: str = 'boxcar') -> np.ndarray:
|
|
12
|
+
"""
|
|
13
|
+
Apply separable DCT smoothing to N-D Cartesian data.
|
|
14
|
+
|
|
15
|
+
The smoothing is applied sequentially along each axis using the same
|
|
16
|
+
kernel type and width (isotropic smoothing).
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
data : np.ndarray
|
|
21
|
+
Input data array (any dimension).
|
|
22
|
+
width : float
|
|
23
|
+
Smoothing width.
|
|
24
|
+
kernel_type : str, default='boxcar'
|
|
25
|
+
Kernel type ('boxcar', 'boxcar_discrete', 'gaussian').
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
smoothed : np.ndarray
|
|
30
|
+
Smoothed data with same shape as input.
|
|
31
|
+
"""
|
|
32
|
+
result = data.copy()
|
|
33
|
+
ndim = data.ndim
|
|
34
|
+
|
|
35
|
+
# Apply 1D smoothing along each axis
|
|
36
|
+
for axis in range(ndim):
|
|
37
|
+
n = data.shape[axis]
|
|
38
|
+
H = get_dct_transfer_function(n, kernel_type, width)
|
|
39
|
+
result = dct_convolve_1d(result, H, axis=axis)
|
|
40
|
+
|
|
41
|
+
return result
|
dct_toolkit/core.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core DCT Primitives and Transfer Functions.
|
|
3
|
+
|
|
4
|
+
This module provides the low-level building blocks for DCT-based smoothing:
|
|
5
|
+
1. Analytical and discrete transfer functions (H[k])
|
|
6
|
+
2. 1D convolution primitive using DCT-II/Ortho
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
import scipy.fft
|
|
11
|
+
|
|
12
|
+
def get_dct_transfer_function(n: int, kernel_type: str, width: float) -> np.ndarray:
|
|
13
|
+
"""
|
|
14
|
+
Generate the 1D DCT Transfer Function H[k].
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
n : int
|
|
19
|
+
Number of points.
|
|
20
|
+
kernel_type : str
|
|
21
|
+
'boxcar', 'boxcar_discrete', or 'gaussian'.
|
|
22
|
+
width : float
|
|
23
|
+
Kernel width.
|
|
24
|
+
- boxcar: full width
|
|
25
|
+
- gaussian: equivalent boxcar width (sigma = width / sqrt(12))
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
H : np.ndarray
|
|
30
|
+
Transfer function of shape (n,).
|
|
31
|
+
"""
|
|
32
|
+
k = np.arange(n)
|
|
33
|
+
|
|
34
|
+
if kernel_type == 'boxcar':
|
|
35
|
+
# Analytical Boxcar: H = sin(W * theta) / (W * sin(theta))
|
|
36
|
+
# where theta = pi * k / (2*n)
|
|
37
|
+
theta_half = (np.pi * k) / (2 * n)
|
|
38
|
+
|
|
39
|
+
H = np.zeros(n)
|
|
40
|
+
H[0] = 1.0
|
|
41
|
+
|
|
42
|
+
mask = k > 0
|
|
43
|
+
if np.any(mask):
|
|
44
|
+
numerator = np.sin(width * theta_half[mask])
|
|
45
|
+
denominator = np.sin(theta_half[mask])
|
|
46
|
+
|
|
47
|
+
# Avoid division by zero
|
|
48
|
+
valid = np.abs(denominator) > 1e-15
|
|
49
|
+
safe_mask = np.zeros_like(mask)
|
|
50
|
+
safe_mask[mask] = valid
|
|
51
|
+
|
|
52
|
+
if np.any(safe_mask):
|
|
53
|
+
H[safe_mask] = numerator[safe_mask[mask]] / (denominator[safe_mask[mask]] * width)
|
|
54
|
+
|
|
55
|
+
return H
|
|
56
|
+
|
|
57
|
+
elif kernel_type == 'boxcar_discrete':
|
|
58
|
+
# Discrete Boxcar Sum
|
|
59
|
+
# H[k] = (1 + 2*sum_{j=1}^{m} cos(j*w_k)) / w_int
|
|
60
|
+
w_int = int(np.round(width))
|
|
61
|
+
if w_int < 1: w_int = 1
|
|
62
|
+
if w_int % 2 == 0: w_int += 1
|
|
63
|
+
|
|
64
|
+
w_k = (np.pi * k) / n
|
|
65
|
+
H = np.ones(n)
|
|
66
|
+
half_width = (w_int - 1) // 2
|
|
67
|
+
|
|
68
|
+
for j in range(1, half_width + 1):
|
|
69
|
+
H += 2 * np.cos(j * w_k)
|
|
70
|
+
|
|
71
|
+
H /= w_int
|
|
72
|
+
return H
|
|
73
|
+
|
|
74
|
+
elif kernel_type == 'gaussian':
|
|
75
|
+
# Gaussian: sigma = width / sqrt(12)
|
|
76
|
+
sigma = width / np.sqrt(12)
|
|
77
|
+
if sigma < 1e-9:
|
|
78
|
+
return np.ones(n)
|
|
79
|
+
|
|
80
|
+
# omega_k = pi * k / n
|
|
81
|
+
omega_k = (np.pi * k) / n
|
|
82
|
+
return np.exp(-0.5 * (omega_k * sigma)**2)
|
|
83
|
+
|
|
84
|
+
else:
|
|
85
|
+
raise ValueError(f"Unknown kernel type: {kernel_type}")
|
|
86
|
+
|
|
87
|
+
def dct_convolve_1d(data: np.ndarray, H: np.ndarray, axis: int = -1) -> np.ndarray:
|
|
88
|
+
"""
|
|
89
|
+
Apply 1D DCT-based convolution.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
data : np.ndarray
|
|
94
|
+
Input data.
|
|
95
|
+
H : np.ndarray
|
|
96
|
+
Transfer function (must match data.shape[axis]).
|
|
97
|
+
axis : int
|
|
98
|
+
Axis to smooth along.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
smoothed : np.ndarray
|
|
103
|
+
Smoothed data.
|
|
104
|
+
"""
|
|
105
|
+
# Validate shapes
|
|
106
|
+
if data.shape[axis] != len(H):
|
|
107
|
+
raise ValueError(f"Transfer function length {len(H)} does not match data dimension {data.shape[axis]}")
|
|
108
|
+
|
|
109
|
+
# Broadcast H to data shape
|
|
110
|
+
shape = [1] * data.ndim
|
|
111
|
+
shape[axis] = len(H)
|
|
112
|
+
H_reshaped = H.reshape(shape)
|
|
113
|
+
|
|
114
|
+
# Forward DCT (Type-II, Ortho)
|
|
115
|
+
X = scipy.fft.dct(data, axis=axis, type=2, norm='ortho')
|
|
116
|
+
|
|
117
|
+
# Apply transfer function
|
|
118
|
+
Y = X * H_reshaped
|
|
119
|
+
|
|
120
|
+
# Inverse DCT (Type-II, Ortho)
|
|
121
|
+
y = scipy.fft.idct(Y, axis=axis, type=2, norm='ortho')
|
|
122
|
+
|
|
123
|
+
return y
|