MutableMultiLevelMODWTResult.java
package com.morphiqlabs.wavelet.modwt;
/**
* Mutable extension of MultiLevelMODWTResult that allows direct coefficient modification.
*
* <p>This interface is designed for applications that need to manipulate wavelet coefficients
* directly, such as thresholding for denoising, coefficient filtering, or implementing
* custom processing algorithms like those used in the Stationary Wavelet Transform (SWT).</p>
*
* <p><strong>Warning:</strong> Direct coefficient modification can break the wavelet
* representation's mathematical properties. Ensure modifications are appropriate for
* your use case and consider the impact on reconstruction accuracy.</p>
*
* <p><strong>Thread Safety:</strong> Implementations are not thread-safe. External
* synchronization is required for concurrent access.</p>
*
* @since 1.0.0
*/
public interface MutableMultiLevelMODWTResult extends MultiLevelMODWTResult {
/**
* Gets a mutable reference to the detail coefficients at a specific level.
*
* <p>Changes to the returned array directly affect the result. Use with caution.</p>
*
* @param level the decomposition level (1 = finest details)
* @return mutable detail coefficients array
* @throws IllegalArgumentException if level is out of range
*/
double[] getMutableDetailCoeffs(int level);
/**
* Sets new detail coefficients at a specific level.
*
* <p>The provided array is copied internally to prevent external modifications.</p>
*
* @param level the decomposition level (1 = finest details)
* @param coeffs new detail coefficients (must match signal length)
* @throws IllegalArgumentException if level is out of range or coeffs has wrong length
* @throws NullPointerException if coeffs is null
*/
void setDetailCoeffs(int level, double[] coeffs);
/**
* Gets a mutable reference to the approximation coefficients.
*
* <p>Changes to the returned array directly affect the result. Use with caution.</p>
*
* @return mutable approximation coefficients array
*/
double[] getMutableApproximationCoeffs();
/**
* Sets new approximation coefficients.
*
* <p>The provided array is copied internally to prevent external modifications.</p>
*
* @param coeffs new approximation coefficients (must match signal length)
* @throws IllegalArgumentException if coeffs has wrong length
* @throws NullPointerException if coeffs is null
*/
void setApproximationCoeffs(double[] coeffs);
/**
* Clears any cached values (e.g., energy calculations) after coefficient modification.
*
* <p>This method should be called after directly modifying coefficients through
* getMutableDetailCoeffs() or getMutableApproximationCoeffs() to ensure
* cached values are recalculated.</p>
*/
void clearCaches();
/**
* Applies a threshold to coefficients at a specific level.
*
* <p>This is a convenience method for coefficient thresholding, commonly used
* in denoising applications.</p>
*
* @param level the decomposition level (0 for approximation, 1+ for details)
* @param threshold the threshold value
* @param soft if true, applies soft thresholding; if false, applies hard thresholding
*/
default void applyThreshold(int level, double threshold, boolean soft) {
if (level == 0) {
double[] coeffs = getMutableApproximationCoeffs();
applyThresholdToArray(coeffs, threshold, soft);
} else {
double[] coeffs = getMutableDetailCoeffs(level);
applyThresholdToArray(coeffs, threshold, soft);
}
clearCaches();
}
/**
* Helper method to apply thresholding to an array.
*/
private static void applyThresholdToArray(double[] coeffs, double threshold, boolean soft) {
for (int i = 0; i < coeffs.length; i++) {
double absValue = Math.abs(coeffs[i]);
if (soft) {
// Soft thresholding: shrink towards zero
if (absValue > threshold) {
coeffs[i] = Math.signum(coeffs[i]) * (absValue - threshold);
} else {
coeffs[i] = 0.0;
}
} else {
// Hard thresholding: set to zero if below threshold
if (absValue <= threshold) {
coeffs[i] = 0.0;
}
}
}
}
/**
* Creates an immutable copy of this result.
*
* <p>The returned result cannot be modified and is safe to share across threads.</p>
*
* @return immutable copy of this result
*/
MultiLevelMODWTResult toImmutable();
}