This guide provides a comprehensive overview of the core functionalities and best practices for the CCMA library.
The CCMA library is designed in an object-oriented style. To begin, initialize the CCMA object:
from ccma import CCMA
ccma = CCMA()
During initialization, the CCMA object prepares kernels and sets filtering width parameters. You can customize the filtering for moving average over points (w_ma
) and moving average for curvature correction (w_cc
) during initialization:
ccma = CCMA(w_ma=3, w_cc=2)
Once the CCMA object is initialized, you can smooth a sequence of N points, provided as a NumPy array with dimensions Nx2 or Nx3:
smoothed_points = ccma.filter(noisy_points)
The CCMA utilizes kernels to determine weights for convolution operations. Several predefined kernels are available:
- Uniform (Rectangular) [
uniform
]—Assigns equal weights to all points. - Pascal's Triangle (Default) [
pascal
]—A discrete Gaussian distribution, balancing accuracy and smoothness. - Hanning (Raised Cosine) [
hanning
]—Ideal for signal processing, particularly effective for smoothing. - Truncated Gaussian [
normal
]—Versatile kernel with adjustable cutoff areas (rho_ma
andrho_cc
).
Specify a kernel during initialization:
ccma = CCMA(distrib="pascal")
For the truncated Gaussian kernel, you can set the cutoff area:
ccma = CCMA(distrib="normal", rho_ma=0.95, rho_cc=0.9)
If the provided kernels don't meet your requirements, define your own kernel function:
ccma = CCMA(distrib=get_triangle_kernel)
Here's an example of a custom triangle kernel:
import numpy as np
def get_triangle_kernel(width):
ramp = np.array(range(1, width + 1))
half_width = width // 2 + 1
ramp[-half_width:] = ramp[:half_width][::-1]
triangle_kernel = ramp / np.sum(ramp)
return triangle_kernel
Note
Kernel width is always an odd value (e.g., 1, 3, 5, ...).
Tip
Start with pascal
or hanning
for general use. Avoid uniform
unless you have specific requirements.
If you wish to employ distinct kernels for smoothing and curvature correction,
you have the flexibility to do so by specifying distrib_ma
and distrib_cc
.
In scenarios where both distrib_ma
and distrib
are set,
the former takes precedence. The same rule applies to distrib_cc
.
ccma = CCMA(w_ma=5, w_cc=2, distrib_ma="hanning")
In this example, the hanning
kernel is designated for smoothing,
while the pascal
kernel is automatically assigned for curvature correction since no specific distrib_cc
is set.
Consequently, the default distrib
specification, which is set to pascal
,
is utilized for curvature correction.
Tip
Using hanning
for smoothing and pascal
for curvature correction can be a strategic approach.
Leveraging the beneficial characteristics of the hanning
kernel for smoothing
and then the accuracy of the pascal
kernel for curvature reconstruction.
Similar to convolution, boundaries require additional handling. Different strategies are available:
- None [
none
]—No boundary strategy is applied. - Padding
padding
]—Replicate the last points on each end forw_ccma
times. - Wrapping [
wrapping
]—Treat the sequence as closed/periodic, adding the first and lastw_ccma
points to the opposite end. - Decreasing Filtering Width [
fill_boundary
]—Filter the ends with decreasing width, trying to maintain equality betweenw_ma
andw_cc
. Furthermore, the objective isw_ma
>=w_cc
Example:
ccma = CCMA(mode="fill_boundary", w_ma=1, w_cc=2)
This would result in the following decreasing filtering parameters at the boundaries:
>>> ccma._get_descending_width()
[{'w_ma': 1, 'w_cc': 1}, {'w_ma': 1, 'w_cc': 0}, {'w_ma': 0, 'w_cc': 0}]
To apply only the moving average without curvature correction, set cc_mode
to False
:
ccma = CCMA()
# Apply the moving average without curvature correction
ccma.filter(noisy_points, cc_mode=False)
If you have additional insights or suggestions to enhance the overall quality and utility of the code, please feel free to share them. Your input is highly valued, and any ideas for improvement that contribute to the code's clarity, efficiency, or user-friendliness will be greatly appreciated.
Thank you in advance for your constructive feedback!