/*
* Created on Oct 9, 2005
*/
package org.seqcode.gseutils;
import java.util.*;
import org.seqcode.gseutils.Pair;
/**
* @author tdanford
*/
public class RealValuedHistogram {
private double start, stop;
private double[] bins;
private double binWidth;
private double totalCount;
public RealValuedHistogram(double start, double stop, int divs) {
bins = new double[divs+2];
for(int i = 0; i < bins.length; i++) {
bins[i] = 0;
}
totalCount = 0;
this.start = start;
this.stop = stop;
binWidth = (stop-start) / (double)divs;
}
public int getNumBins() { return bins.length; }
public double getTotalCount() { return totalCount; }
public double getMaxBinCount(){
double max=0;
for(int x=0; x<bins.length; x++){
if(bins[x]>max){max=bins[x];}
}return(max);
}
public double getMinBinCount(){
double min=Integer.MAX_VALUE;
for(int x=0; x<bins.length; x++){
if(bins[x]<min){min=bins[x];}
}return(min);
}
public void addToBin(int b, double c) {
bins[b] += c;
totalCount += c;
}
public double getBin(int b) { return bins[b]; }
public double [] getBins(){return bins;}
public double getBinFraction(int b) {
if(totalCount == 0) { return 0.0; }
return bins[b]/totalCount;
}
public double[] cumulativeFromLeft() {
double[] cdf = new double[bins.length];
double seen = 0;
for(int i = 0; i < cdf.length; i++) {
seen += bins[i];
cdf[i] = 0.0;
if(totalCount > 0) {
cdf[i] = seen / totalCount;
}
}
return cdf;
}
public double[] cumulativeFromRight() {
double[] cdf = new double[bins.length];
double seen = 0;
for(int i = cdf.length-1; i >= 0; i--) {
seen += bins[i];
cdf[cdf.length-1-i] = 0.0;
if(totalCount > 0) {
cdf[cdf.length-1-i] = seen / totalCount;
}
}
return cdf;
}
public void addValue(int v){addValue((double)v, 1.0);}
public void addValue(double v){addValue(v, 1.0);}
public void addValue(double v, double weight) {
if(v < start) { addToBin(0, weight); return; }
if(v >= stop) { addToBin(getNumBins()-1, weight); return; }
int bin = (int)Math.floor((v-start) / binWidth) + 1;
addToBin(bin, weight);
}
public void addValues(ArrayList<Double> vals){
for(Double d : vals)
addValue(d);
}
public void addValueRange(double v1, double v2) {addValueRange(v1,v2,1.0);}
public void addValueRange(double v1, double v2, double weight) {
double vstart = v1;
double vend = v2;
if(vstart < start) { vstart=start; }
if(vend >= stop) {vend = stop;}
double v = vstart;
while(v<=vend){
int bin = (int)Math.floor((v-start) / binWidth) + 1;
addToBin(bin, weight);
v+=binWidth;
}
}
public int getBinContainingVal(double val){
if(val < start) { return 0; }
if(val >= stop) { return getNumBins()-1; }
int bin = (int)Math.floor((val-start) / binWidth) + 1;
return(bin);
}
public Pair<Double,Double> getBinBounds(int b) {
Double left = null, right = null;
if(b == 0) {
right = start;
} else if (b == getNumBins()-1) {
left = stop;
} else {
int effB = b - 1;
left = start + (double)effB * binWidth;
right = start + (double)(effB + 1) * binWidth;
}
return new Pair<Double,Double>(left, right);
}
public void addHistogram(RealValuedHistogram h){
if(getNumBins() != h.getNumBins()){
System.err.println("Bin numbers not the same; cannot add histograms");
}else{
for(int x=0; x<bins.length; x++){
bins[x]+=h.getBin(x);
}
}
}
public void subtractHistogram(RealValuedHistogram h){
if(getNumBins() != h.getNumBins()){
System.err.println("Bin numbers not the same; cannot subtract histograms");
}else{
for(int x=0; x<bins.length; x++){
bins[x]-=h.getBin(x);
}
}
}
public void divideByHistogram(RealValuedHistogram h){
if(getNumBins() != h.getNumBins()){
System.err.println("Bin numbers not the same; cannot divide histograms");
}else{
for(int x=0; x<bins.length; x++){
if(h.getBin(x)>0){bins[x]=bins[x]/h.getBin(x);}
}
}
}
public double getHistoStart(){return start;}
public double getHistoStop(){return stop;}
public void printContents(){printContents(false);}
public void printContents(boolean toErr){
if(!toErr){
System.out.println(String.format("Less\t%f", bins[0]));
for(int i = 1; i < bins.length-1; i++)
System.out.println(String.format("%f\t%f", start+((double)(i-1)*binWidth), bins[i]));
System.out.println(String.format("More\t%f", bins[bins.length-1]));
}else{
System.err.println(String.format("Less\t%f", bins[0]));
for(int i = 1; i < bins.length-1; i++)
System.err.println(String.format("%f\t%f", start+((double)(i-1)*binWidth), bins[i]));
System.err.println(String.format("More\t%f", bins[bins.length-1]));
}
}
public String contentsToString(){
String contents=String.format("Less\t%.2f\n", bins[0]);
for(int i = 1; i < bins.length-1; i++) {
contents = contents+String.format("%.1f\t%.2f\n", start+((double)(i-1)*binWidth), bins[i]);
}
contents = contents+String.format("More\t%.2f\n", bins[bins.length-1]);
return contents;
}
}