package org.openlca.app.results.simulation;
import java.util.List;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.GridLayout;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.geometry.Point;
import org.openlca.app.util.Numbers;
import org.openlca.core.results.SimulationStatistics;
/**
* Draws a chart with a frequency distribution and statistic parameters.
*/
public class StatisticFigure extends Figure {
private SimulationStatistics statistics = SimulationStatistics.empty();
private int marginLeft = 35;
private int marginBottom = 35;
private int marginRight = 25;
private int marginTop = 25;
private Label numberLabel;
private Label perc5Label;
private Label perc95Label;
private Label medianLabel;
private Label meanLabel;
private Label standardDevLabel;
public StatisticFigure() {
setOpaque(true);
setBackgroundColor(ColorConstants.white);
setForegroundColor(ColorConstants.black);
setBorder(new LineBorder(ColorConstants.black, 1));
GridLayout gl = new GridLayout();
gl.numColumns = 12;
setLayoutManager(gl);
numberLabel = initLabel("results");
meanLabel = initLabel("mean");
standardDevLabel = initLabel("standard deviation");
perc5Label = initLabel("5% percentile");
perc95Label = initLabel("95% percentile");
medianLabel = initLabel("median");
}
private Label initLabel(String text) {
Label textLabel = new Label(text + ":");
textLabel.setForegroundColor(ColorConstants.blue);
Label valueLabel = new Label("0");
valueLabel.setForegroundColor(ColorConstants.black);
add(textLabel);
add(valueLabel);
return valueLabel;
}
public void setData(List<Double> values) {
statistics = new SimulationStatistics(values, 100);
repaint();
}
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
graphics.pushState();
paintParameterLabels();
paintChartFrame(graphics);
Point boxSize = calcBoxSize();
paintBoxes(graphics, boxSize);
paintLines(graphics, boxSize);
graphics.popState();
}
private void paintBoxes(Graphics graphics, Point boxSize) {
graphics.setBackgroundColor(ColorConstants.lightGray);
int height = getSize().height - marginBottom;
for (int interval = 0; interval < 100; interval++) {
int frequency = statistics.getAbsoluteFrequency(interval);
for (int block = 1; block <= frequency; block++) {
int x = marginLeft + interval * boxSize.x;
int y = height - block * boxSize.y;
if (y >= marginTop)
drawBox(graphics, boxSize, new Point(x, y));
}
}
graphics.setBackgroundColor(ColorConstants.white);
}
private void drawBox(Graphics graphics, Point boxSize, Point topLeft) {
graphics.drawRectangle(topLeft.x, topLeft.y, boxSize.x, boxSize.y);
graphics.fillRectangle(topLeft.x + 1, topLeft.y + 1, boxSize.x - 1,
boxSize.y - 1);
}
private void paintParameterLabels() {
numberLabel.setText(statistics.getCount() + "");
setLabelValue(perc5Label, statistics.getPercentileValue(5));
setLabelValue(perc95Label, statistics.getPercentileValue(95));
setLabelValue(medianLabel, statistics.getMedian());
setLabelValue(meanLabel, statistics.getMean());
setLabelValue(standardDevLabel, statistics.getStandardDeviation());
}
private void paintChartFrame(Graphics graphics) {
graphics.drawLine(marginLeft, getSize().height - marginBottom,
getSize().width - marginRight, getSize().height - marginBottom);
graphics.drawLine(marginLeft, marginTop, marginLeft, getSize().height
- marginBottom);
graphics.drawText(Numbers.format(statistics.getMinimum(), 3),
marginLeft, getSize().height - marginBottom + 10);
graphics.drawText(Numbers.format(statistics.getMaximum(), 3),
getSize().width - marginRight - 40, getSize().height
- marginBottom + 10);
graphics.drawText(
Integer.toString(statistics.getMaximalAbsoluteFrequency()), 15,
marginTop + 5);
graphics.drawText("0", 15, getSize().height - marginBottom - 15);
}
private Point calcBoxSize() {
Point size = new Point();
int width = getSize().width - marginLeft - marginRight;
int height = getSize().height - marginTop - marginBottom;
int intervalCount = 100;
int maxFreq = statistics.getMaximalAbsoluteFrequency();
if (maxFreq > height) {
double factor = (double) maxFreq / (double) height;
maxFreq /= factor;
}
size.x = width / intervalCount;
size.y = height / maxFreq;
if (size.x < 1)
size.x = 1;
if (size.y < 1)
size.y = 1;
return size;
}
private void paintLines(Graphics graphics, Point boxSize) {
graphics.setForegroundColor(ColorConstants.red);
drawLine(graphics, statistics.getPercentileValue(5), boxSize);
drawLine(graphics, statistics.getMedian(), boxSize);
drawLine(graphics, statistics.getPercentileValue(95), boxSize);
drawLine(graphics, statistics.getMean(), boxSize);
graphics.setForegroundColor(ColorConstants.black);
}
private void drawLine(Graphics graphics, double val, Point boxSize) {
int interval = statistics.getInterval(val);
int x = boxSize.x * interval + marginLeft + boxSize.x / 2;
graphics.drawLine(x, getSize().height - marginBottom, x, marginTop);
}
private void setLabelValue(Label label, double val) {
label.setText(Numbers.format(val, 3));
}
}