edu.cuny.qc.speech.AuToBI.core.Aggregation.java Source code

Java tutorial

Introduction

Here is the source code for edu.cuny.qc.speech.AuToBI.core.Aggregation.java

Source

/*  Aggregation.java
    
Copyright (c) 2009-2014 Andrew Rosenberg
    
  This file is part of the AuToBI prosodic analysis package.
    
  AuToBI is free software: you can redistribute it and/or modify
  it under the terms of the Apache License (see boilerplate below)
    
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You should have received a copy of the Apache 2.0 License along with AuToBI.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 */
package edu.cuny.qc.speech.AuToBI.core;

import java.util.Collection;
import java.io.Serializable;

import static org.apache.commons.math3.special.Erf.erf;

/**
 * A class to store aggregations of real numbered information.
 * <p/>
 * Aggregation is used to store and serialize running means and standard deviations of values such as pitch and
 * intensity.
 */
public class Aggregation implements Serializable {
    private static final long serialVersionUID = 2012709453361591892L;

    private String label; // an optional label for the aggregation
    private Double min; // the maximum value in the aggregation
    private Double max; // the minimum value in the aggregation
    private Double sum; // the sum of all values added to the aggregation
    private Double ssq; // the sum of squares of all values added to the aggregation
    private Integer n; // the number of elements in the aggregation

    /**
     * Constructs a new Aggregation
     */
    public Aggregation() {
        this.label = "";
        this.min = Double.MAX_VALUE;
        this.max = -Double.MAX_VALUE;
        this.sum = 0.0;
        this.ssq = 0.0;
        this.n = 0;
    }

    /**
     * Constructs a new Aggregation with a label
     *
     * @param label the label
     */
    public Aggregation(String label) {
        this();
        this.label = label;
    }

    /**
     * Sets the label.
     *
     * @param label The new label
     */
    public void setLabel(String label) {
        this.label = label;
    }

    /**
     * Gets the label
     *
     * @return label
     */
    public String getLabel() {
        return label;
    }

    /**
     * Inserts a new value in the Aggregation
     *
     * @param v the value
     */
    public void insert(Double v) {
        sum += v;
        ssq += (v * v);
        max = (max == null) ? v : Math.max(max, v);
        min = (min == null) ? v : Math.min(min, v);
        n++;
    }

    /**
     * Removes a value from the Aggregation.
     * <p/>
     * Removing a value from an Aggregation can invalidate its minimum and maximum calculation if the value was equal to
     * the current minmum or maximum.
     * <p/>
     * Note: no check is made that the value was ever initially added to the Aggregation.
     *
     * @param v the value
     */
    public void remove(Double v) {
        sum -= v;
        ssq -= (v * v);
        if (v.equals(max)) {
            max = Double.NaN; // no running max and min
        }
        if (v.equals(min)) {
            min = Double.NaN;
        }
        n--;
    }

    /**
     * Inserts a Collection of values.
     *
     * @param values the values
     */
    public void insert(Collection<Double> values) {
        for (Double d : values)
            this.insert(d);
    }

    /**
     * Removes a Collection of values.
     *
     * @param values the values
     */
    public void remove(Collection<Double> values) {
        for (Double d : values)
            this.remove(d);
    }

    /**
     * Calculates the mean value.
     * <p/>
     * If there are no elements in the Aggregation, the mean is zero.
     *
     * @return the mean
     */
    public Double getMean() {
        if (n < 1)
            return 0.0;
        return sum / n;
    }

    /**
     * Calculates the standard deviation.
     * <p/>
     * If there are less than 2 elements in the Aggregation, the standard deviation is zero.
     *
     * @return the standard deviation
     */
    public Double getStdev() {
        if (n < 2)
            return 0.0;

        return Math.sqrt(getVariance());
    }

    /**
     * Calculates the variance
     * <p/>
     * If there are less than 2 elements in the Aggregation, the variance is zero.
     *
     * @return the variance
     */
    public Double getVariance() {
        if (n < 2)
            return 0.0;

        Double mean = sum / n;
        return (ssq - (n * mean * mean)) / (n - 1);
    }

    /**
     * Calculates the root mean squared value.
     *
     * @return the rms
     */
    public Double getRMS() {
        return Math.sqrt(ssq / n);
    }

    /**
     * Retrieves the minimum value.
     *
     * @return the minimum
     */
    public Double getMin() {
        return min;
    }

    /**
     * Overrides the current min with an externally calculated value
     * <p/>
     * This is helpful if the minimum value gets invalidated by remove.
     *
     * @param min the minimum value
     */
    public void setMin(Double min) {
        this.min = min;
    }

    /**
     * Retrieves the maximum value.
     *
     * @return the maximum
     */
    public Double getMax() {
        return max;
    }

    /**
     * Overrides the current max with an externally calculated value
     * <p/>
     * This is helpful if the maximum value gets invalidated by remove.
     *
     * @param max the maximum value
     */
    public void setMax(Double max) {
        this.max = max;
    }

    /**
     * Retrieves the number of elements.
     *
     * @return the number of elements.
     */
    public int getSize() {
        return n;
    }

    /**
     * Treating this aggregation as a Gaussian probability distribution function, evaluates the probability that a value
     * generated was generated by this aggregation.
     *
     * @param value the value to evaluate
     * @return the gaussian PDF evaluated at value
     */
    public double evaluateGaussianPDF(double value) {
        double mean = getMean();
        double stdev = getStdev();

        double pdf = 1 / (stdev * Math.sqrt(2 * Math.PI));
        pdf *= Math.pow(Math.E, (-(value - mean) * (value - mean)) / (2 * stdev * stdev));
        return pdf;
    }

    /**
     * Evaluates the CDF of the aggregation.  The aggregation is treated as a Gaussian distribution in this case
     * <p/>
     * The CDF is the probability of a value drawn from the distribution falling below f
     * <p/>
     * cdf(x) = 1/2 [1 + erf(x - mu/sqrt(2 * stdev^2))]
     *
     * @param value the value
     * @return the CDF
     */
    public double evaluateGaussianCDF(double value) {
        double stdev = getStdev();
        return .5 * (1 + erf((value - getMean()) / Math.sqrt(2 * stdev * stdev)));
    }

    /**
     * Generates a descriprion of the Aggregation
     *
     * @return the description
     */
    public String toString() {
        String s = "";
        s += "mean: " + getMean();
        s += " stdev: " + getStdev();
        s += " variance: " + getVariance();
        s += " stderr: " + (getStdev() / getSize());
        s += " min: " + getMin();
        s += " max: " + getMax();
        return s;
    }
}