package com.compomics.util.math.statistics.distributions;
import com.compomics.util.math.BasicMathFunctions;
import com.compomics.util.math.statistics.Distribution;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Collections;
import org.apache.commons.math.MathException;
/**
* This class represents a non symmetrical normal distribution.
*
* @author Marc Vaudel
*/
public class NonSymmetricalNormalDistribution implements Distribution {
/**
* Serial version number for backward compatibility.
*/
static final long serialVersionUID = -5258258835569357886L;
/**
* The standard deviation on the right of the distribution.
*/
private double stdUp;
/**
* The standard deviation on the left of the distribution.
*/
private double stdDown;
/**
* The mean.
*/
private double mean;
/**
* Distribution equivalent to the right of the distribution.
*/
private NormalDistribution distributionUp;
/**
* Distribution equivalent to the left of the distribution.
*/
private NormalDistribution distributionDown;
/**
* Constructor.
*
* @param mean the mean
* @param stdDown the standard deviation on the left of the mean
* @param stdUp the standard deviation on the right of the mean
*/
public NonSymmetricalNormalDistribution(double mean, double stdDown, double stdUp) {
this.mean = mean;
this.stdDown = stdDown;
this.stdUp = stdUp;
this.distributionDown = new NormalDistribution(mean, stdDown);
this.distributionUp = new NormalDistribution(mean, stdUp);
}
/**
* Returns the standard deviation to the right of the distribution.
*
* @return the standard deviation to the right of the distribution
*/
public double getStdUp() {
return stdUp;
}
/**
* Returns the standard deviation to the left of the distribution.
*
* @return the standard deviation to the left of the distribution
*/
public double getStdDown() {
return stdDown;
}
/**
* Returns the mean of the distribution.
*
* @return the mean of the distribution
*/
public double getMean() {
return mean;
}
/**
* Returns the non-symmetrical distribution of the input list of double
* calibrated on the median, 15.9% and 84.1% percentiles.
*
* @param input the input list
* @return the non symmetrical distribution calibrated on the median, 15.9%
* and 84.1% percentiles.
*/
public static NonSymmetricalNormalDistribution getRobustNonSymmetricalNormalDistribution(ArrayList<Double> input) {
ArrayList<Double> sortedInput = new ArrayList<Double>(input);
Collections.sort(sortedInput);
return getRobustNonSymmetricalNormalDistributionFromSortedList(sortedInput);
}
/**
* Returns the non-symmetrical distribution of the input list of double
* calibrated on the median, 15.9% and 84.1% percentiles.
*
* @param input the input list
* @return the non symmetrical distribution calibrated on the median, 15.9%
* and 84.1% percentiles.
*/
public static NonSymmetricalNormalDistribution getRobustNonSymmetricalNormalDistributionFromSortedList(ArrayList<Double> input) {
double median = BasicMathFunctions.medianSorted(input);
double percentileDown = BasicMathFunctions.percentileSorted(input, 0.159);
double percentileUp = BasicMathFunctions.percentileSorted(input, 0.841);
return new NonSymmetricalNormalDistribution(median, median - percentileDown, percentileUp - median);
}
@Override
public Double getProbabilityAt(double x) {
if (x >= mean) {
return distributionUp.getProbabilityAt(x);
} else {
return distributionDown.getProbabilityAt(x);
}
}
@Override
public Double getCumulativeProbabilityAt(double x) throws MathException {
if (x >= mean) {
return distributionUp.getCumulativeProbabilityAt(x);
} else {
return distributionDown.getCumulativeProbabilityAt(x);
}
}
@Override
public Double getDescendingCumulativeProbabilityAt(double x) throws MathException {
if (x > mean) {
return distributionUp.getDescendingCumulativeProbabilityAt(x);
} else {
return distributionDown.getDescendingCumulativeProbabilityAt(x);
}
}
@Override
public Double getSmallestCumulativeProbabilityAt(double x) throws MathException {
if (x > mean) {
return getDescendingCumulativeProbabilityAt(x);
} else {
getCumulativeProbabilityAt(x);
}
return 0.5;
}
@Override
public Double getMaxValueForProbability(double p) {
return distributionUp.getMaxValueForProbability(p);
}
@Override
public Double getMinValueForProbability(double p) {
return distributionDown.getMinValueForProbability(p);
}
@Override
public Double getValueAtCumulativeProbability(double p) throws MathException {
if (p < 0.5) {
return distributionDown.getValueAtCumulativeProbability(p);
} else {
return distributionUp.getValueAtCumulativeProbability(p);
}
}
@Override
public Double getValueAtDescendingCumulativeProbability(double p) throws MathException {
if (p < 0.5) {
return distributionUp.getValueAtDescendingCumulativeProbability(p);
} else {
return distributionDown.getValueAtDescendingCumulativeProbability(p);
}
}
}