001/* *********************************************************************** * 002 * project: org.matsim.* 003 * * 004 * *********************************************************************** * 005 * * 006 * copyright : (C) 2012 by the members listed in the COPYING, * 007 * LICENSE and WARRANTY file. * 008 * email : info at matsim dot org * 009 * * 010 * *********************************************************************** * 011 * * 012 * This program is free software; you can redistribute it and/or modify * 013 * it under the terms of the GNU General Public License as published by * 014 * the Free Software Foundation; either version 2 of the License, or * 015 * (at your option) any later version. * 016 * See also COPYING, LICENSE and WARRANTY file * 017 * * 018 * *********************************************************************** */ 019 020package org.matsim.analysis; 021 022import java.io.BufferedWriter; 023import java.io.IOException; 024import java.text.DecimalFormat; 025import java.util.Collections; 026import java.util.List; 027import java.util.Vector; 028 029import org.apache.log4j.Logger; 030import org.matsim.core.utils.charts.BarChart; 031import org.matsim.core.utils.io.IOUtils; 032 033public class Bins { 034 035 protected double interval; 036 protected int numberOfBins; 037 protected double maxVal; 038 protected String desc; 039 protected List<BinEntry> entries = new Vector<BinEntry>(); 040 protected double [] bins; 041 042 private final static Logger log = Logger.getLogger(Bins.class); 043 044 public Bins(double interval, double maxVal, String desc) { 045 this.interval = interval; 046 this.maxVal = maxVal; 047 this.numberOfBins = (int)Math.ceil(maxVal / interval); 048 this.desc = desc; 049 this.bins = new double[this.numberOfBins]; 050 } 051 public void addValues(double[] values, double[] weights) { 052 for (int index = 0; index < values.length; index++) { 053 this.addVal(values[index], weights[index]); 054 } 055 } 056 057 public void addVal(double value, double weight) { 058 int index = (int)Math.floor(value / interval); 059 // values > maximum value are assigned to the last bin 060 if (value >= maxVal) { 061 index = this.numberOfBins -1; 062 } 063 064 // values < 0.0 value are assigned to the first bin 065 if (value < 0.0) { 066 log.error("Value < 0.0 received"); 067 index = 0; 068 } 069 070 this.bins[index] += weight; 071 this.entries.add(new BinEntry(value, weight)); 072 } 073 074 public void clear() { 075 this.entries.clear(); 076 this.bins = new double[this.numberOfBins]; 077 } 078 079 public void plotBinnedDistribution(String path, String xLabel, String xUnit) { 080 String [] categories = new String[this.numberOfBins]; 081 for (int i = 0; i < this.numberOfBins; i++) { 082 categories[i] = Integer.toString(i); 083 } 084 Double[] values = new Double[this.entries.size()]; 085 Double[] weights = new Double[this.entries.size()]; 086 087 for (int index = 0; index < this.entries.size(); index++) { 088 values[index] = this.entries.get(index).getValue(); 089 weights[index] = this.entries.get(index).getWeight(); 090 } 091 092 DecimalFormat formatter = new DecimalFormat("0.0000"); 093 String s = xLabel + " " + 094 "[interval = " + formatter.format(this.interval) + xUnit + "]" + 095 "[number of entries = " + this.entries.size() + "]" + 096 "[mean = " + formatter.format(this.weightedMean(values, weights)) + xUnit + "]" + 097 "[median = " + formatter.format(this.median(values)) + xUnit + "]" + 098 "[max = " + formatter.format(this.getMax(values)) + xUnit + "]"; 099 100 BarChart chart = 101 new BarChart(desc, s , "#", categories); 102 chart.addSeries("Bin size", this.bins); 103 chart.saveAsPng(path + desc + ".png", 1600, 800); 104 105 try { 106 BufferedWriter out = IOUtils.getBufferedWriter(path + desc + ".txt"); 107 out.write("Bin [interval = " + this.interval + " " + xUnit + "]\t" + "#" + "\n"); 108 for (int j = 0; j < bins.length; j++) { 109 out.write(j + "\t" + bins[j] + "\n"); 110 } 111 out.flush(); 112 out.close(); 113 } catch (IOException e) { 114 e.printStackTrace(); 115 } 116 } 117 public double[] getBins() { 118 return bins; 119 } 120 public void setBins(double[] bins) { 121 this.bins = bins; 122 } 123 124 public double getInterval() { 125 return interval; 126 } 127 public void setInterval(double interval) { 128 this.interval = interval; 129 } 130 // ---------------------------------------------------------------------------- 131 private double median(Double [] values) { 132 List<Double> list = new Vector<Double>(); 133 134 Collections.addAll(list, values); 135 return median(list); 136 } 137 138 public double median(List<Double> values) { 139 140 if (values.size() == 0) return 0.0; 141 142 Collections.sort(values); 143 if (values.size() % 2 != 0) { 144 return values.get((values.size()+1)/2-1); 145 } 146 else { 147 double lower = values.get(values.size()/2-1); 148 double upper = values.get(values.size()/2); 149 return (lower + upper) / 2.0; 150 } 151 } 152 153 public double mean(List<Double> values) { 154 double sum = 0.0; 155 int cnt = 0; 156 if (values.size() == 0) return 0.0; 157 for (Double value : values) { 158 sum += value; 159 cnt++; 160 } 161 return sum / cnt; 162 } 163 164 public double weightedMean(List<Double> values, List<Double> weights) { 165 return weightedMean(values.toArray(new Double[values.size()]), weights.toArray(new Double[weights.size()])); 166 } 167 168 public double weightedMean(Double[] values, Double[] weights) { 169 double sumValues = 0.0; 170 double sumWeights = 0.0; 171 172 if (values.length == 0) return 0.0; 173 174 if (values.length != weights.length ) { 175 log.info("size of weights and values not identical"); 176 return -1; 177 } 178 for (int index = 0; index < values.length; index++) { 179 sumValues += (values[index] * weights[index]); 180 sumWeights += weights[index]; 181 } 182 return sumValues / sumWeights; 183 } 184 185 public double getMax(List<Double> values) { 186 return getMax(values.toArray(new Double[values.size()])); 187 } 188 189 public double getMax(Double[] values) { 190 double maxVal = Double.MIN_VALUE; 191 for (Double v : values) { 192 if (v > maxVal) { 193 maxVal = v; 194 } 195 } 196 return maxVal; 197 } 198}