FeatureDifference.java
package org.hammer.audio.experimental.acoustic.feature.comparison;
import java.util.Objects;
/**
* Per-feature difference between the synthetic and real corpus means.
*
* @param featureName human-readable feature name; must not be blank
* @param syntheticMean mean feature value in the synthetic corpus
* @param realMean mean feature value in the real corpus
* @param absoluteDifference {@code |realMean - syntheticMean|}; must be finite and {@code >= 0}
* @param relativeDifference {@code absoluteDifference / |syntheticMean|}, or {@code 0} when the
* synthetic mean is zero; must be finite and {@code >= 0}
* @param zScore standardised difference {@code (realMean - syntheticMean) / syntheticStdDev} when
* {@code syntheticStdDev > 0}, or {@code 0}; must be finite
*/
public record FeatureDifference(
String featureName,
double syntheticMean,
double realMean,
double absoluteDifference,
double relativeDifference,
double zScore) {
/** Validate fields. */
public FeatureDifference {
Objects.requireNonNull(featureName, "featureName");
if (featureName.isBlank()) {
throw new IllegalArgumentException("featureName must not be blank");
}
if (!Double.isFinite(syntheticMean)) {
throw new IllegalArgumentException("syntheticMean must be finite");
}
if (!Double.isFinite(realMean)) {
throw new IllegalArgumentException("realMean must be finite");
}
if (!Double.isFinite(absoluteDifference) || absoluteDifference < 0.0) {
throw new IllegalArgumentException("absoluteDifference must be finite and >= 0");
}
if (!Double.isFinite(relativeDifference) || relativeDifference < 0.0) {
throw new IllegalArgumentException("relativeDifference must be finite and >= 0");
}
if (!Double.isFinite(zScore)) {
throw new IllegalArgumentException("zScore must be finite");
}
}
}