io.hummer.util.test.GenericTestResult.java Source code

Java tutorial

Introduction

Here is the source code for io.hummer.util.test.GenericTestResult.java

Source

/*
 * Project 'WS-Aggregation':
 * http://www.infosys.tuwien.ac.at/prototype/WS-Aggregation/
 *
 * Copyright 2010 Vienna University of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 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 io.hummer.util.test;

import io.hummer.util.coll.CollectionsUtil;
import io.hummer.util.cp.ClasspathUtil;
import io.hummer.util.io.IOUtil;
import io.hummer.util.log.LogUtil;
import io.hummer.util.xml.XMLUtil;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.Element;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class GenericTestResult {

    private static final Logger logger = LogUtil.getLogger(GenericTestResult.class);

    // to eliminate "outliers" that possibly influence the overall result
    @XmlTransient
    private int eliminateXlowestValues = 0;
    @XmlTransient
    private int eliminateXhighestValues = 0;
    @XmlTransient
    private NumberFormat f = NumberFormat.getInstance(Locale.US);
    @XmlTransient
    private CollectionsUtil collUtil = new CollectionsUtil();
    @XmlTransient
    private IOUtil ioUtil = new IOUtil();
    @XmlTransient
    private ClasspathUtil cpUtil = new ClasspathUtil();

    public static final String CMD_FLIP_AXES = "##flipaxes";
    public static final String CMD_MULTI_LINE = "##multiline";
    public static final String CMD_DRAW_LINE_THROUGH_CANDLESTICKS = "##linesThroughCandles";
    public static final String CMD_MULTIPLE_CANDLES_PER_XTICK = "##multipleCandles";
    public static final String CMD_NO_LINES_JUST_POINTS = "##onlyPoints";
    public static final String CMD_ONLY_EVERY_2ND_XTICS = "##every2ndXtics";
    public static final String CMD_ONLY_EVERY_3RD_XTICS = "##every3rdXtics";
    public static final String CMD_MULTI_AXES = "##multipleAxes";

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class IterationResult {

        @XmlElement(name = "entry")
        private List<Entry> entries = new LinkedList<Entry>();

        public synchronized void addEntry(String valueName, double value) {
            entries.add(new Entry(valueName, value));
        }

        public synchronized List<Entry> getEntries() {
            return entries;
        }

        public void setEntries(List<Entry> entries) {
            this.entries = entries;
        }

        public void addEntryIfDifferent(String key, double value, String oldKeyPattnern, GenericTestResult parent) {
            List<Double> old = parent.getValuesByPattern(oldKeyPattnern);
            //System.out.println("Old/new value '" + key + "'/'" + oldKeyPattnern + "': " + old + "/" + value);
            if (old.isEmpty() || old.get(old.size() - 1) != value) {
                addEntry(key, value);
            }
        }

        public void addEntryAndRemoveOldIfSame(String keyPattern, String key, double value,
                GenericTestResult parent) {
            List<String> keys = parent.getAllValueNames(keyPattern);
            addEntry(key, value);
            if (keys.size() > 2) {
                String oldKey1 = keys.get(keys.size() - 2);
                String oldKey2 = keys.get(keys.size() - 1);
                Double old1 = parent.getValue(oldKey1);
                Double old2 = parent.getValue(oldKey2);
                if (old1.equals(old2) && old2.equals(value)) {
                    /* remove oldKey2 which lies in the middle between oldKey1 and key */
                    removeEntry(oldKey2);
                }
            }
        }

        public void removeEntry(String name) {
            List<Entry> toRemove = new LinkedList<Entry>();
            for (Entry e : toRemove) {
                if (e.name.equals(name)) {
                    toRemove.add(e);
                }
            }
            for (Entry e : toRemove) {
                entries.remove(e);
            }
        }
    }

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Entry {
        @XmlElement
        private String name;
        @XmlElement
        private Double value;

        public Entry() {
        }

        public Entry(String valueName, double value) {
            this.name = valueName;
            this.value = value;
        }

        public Double getValue() {
            return value;
        }

        public void setValue(double value) {
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static enum ResultType {
        MEAN, THROUGHPUT, REGRESSION
    }

    public static enum EliminationMethod {
        REMOVE_EACH_NTH_ENTRY, CONSIDER_VALUE_DIFFERENCES
    }

    @XmlElement
    private List<IterationResult> iterations = new LinkedList<IterationResult>();
    @XmlElement
    private long startTime;
    @XmlElement
    private long finishTime;

    public GenericTestResult() {
        f.setMaximumFractionDigits(1);
        f.setMinimumFractionDigits(1);
        f.setGroupingUsed(false);
    }

    public void setNumberFormat(int minimumFractionDigits, int maximumFractionDigits) {
        f.setMaximumFractionDigits(maximumFractionDigits);
        f.setMinimumFractionDigits(minimumFractionDigits);
    }

    public IterationResult newIteration() {
        IterationResult i = new IterationResult();
        iterations.add(i);
        return i;
    }

    public double getStdDeviation(String valueName) {
        List<Double> values = getValues(valueName);
        return getStdDeviation(values);
    }

    public double getStdDeviation(List<Double> values) {
        return Math.sqrt(getSampleVariance(values));
    }

    public List<Double> getStdDeviations(String namePattern, List<String> levels) {
        List<Double> result = new LinkedList<Double>();
        for (String level : levels) {
            List<Double> values = getValues(namePattern.replace("<level>", level));
            result.add(getStdDeviation(values));
        }
        return result;
    }

    public double getSampleVariance(String valueName) {
        return getSampleVariance(getValues(valueName));
    }

    public double getSampleVariance(List<Double> values) {
        double mean = getMean(values);
        double sumSquares = 0;
        for (double l : values) {
            double diff = mean - (double) l;
            sumSquares += diff * diff;
        }
        double variance = sumSquares / (double) (values.size() - 1);
        return variance;
    }

    public Double getValue(String valueNameOrPattern) {
        return getValue(valueNameOrPattern, null);
    }

    public Double getValue(String valueNameOrPattern, Double defaultIfNull) {
        List<String> names = getAllValueNames(valueNameOrPattern);
        if (names.size() != 1) {
            logger.debug("Expected a single key for pattern '" + valueNameOrPattern + "', got: " + names);
            return defaultIfNull;
        }
        List<Double> values = getValues(names.get(0), true, false);
        if (values.size() != 1) {
            logger.debug("Expected a single value for key '" + names.get(0) + "', got: " + values);
            return defaultIfNull;
        }
        return values.get(0);
    }

    public List<Double> getValuesByPattern(String valueNamePattern) {
        return getValues(valueNamePattern, true, true);
    }

    public List<Double> getValues(String valueName) {
        return getValues(valueName, true, false);
    }

    public List<Double> getValues(String valueNameOrPattern, boolean addZeroes) {
        return getValues(valueNameOrPattern, addZeroes, false);
    }

    public List<Double> getValues(String valueNameOrPattern, boolean addZeroes, boolean treatNameAsPattern) {
        List<Double> result = new LinkedList<Double>();
        for (IterationResult r : iterations) {
            for (Entry e : r.getEntries()) {
                if ((!treatNameAsPattern && e.getName().equals(valueNameOrPattern))
                        || (treatNameAsPattern && e.getName().matches(valueNameOrPattern))) {
                    double val = e.getValue();
                    if (addZeroes || val != 0.0)
                        result.add(val);
                }
            }
        }
        if (result.size() > eliminateXhighestValues) {
            for (int i = 0; i < eliminateXhighestValues; i++) {
                Double max = Collections.max(result);
                result.remove(max);
            }
        }
        if (result.size() > eliminateXlowestValues) {
            for (int i = 0; i < eliminateXlowestValues; i++) {
                Double min = Collections.min(result);
                result.remove(min);
            }
        }
        return result;
    }

    public double getTotal(String valueName) {
        return getTotal(getValues(valueName));
    }

    public double getTotal(List<Double> values) {
        double total = 0;
        for (Double d : values)
            total += d;
        return total;
    }

    public long getAmount(String valueName) {
        return getValues(valueName).size();
    }

    public double getMean(String valueName) {
        return getMean(getValues(valueName));
    }

    public double getMean(List<Double> values) {
        return getTotal(values) / (double) values.size();
    }

    public double getMedian(String valueName) {
        return getMedian(getValues(valueName));
    }

    public double getMedian(List<Double> values) {
        List<Double> copy = new ArrayList<Double>(values);
        Collections.sort(copy);
        return copy.get((int) ((double) copy.size() / 2.0));
    }

    public double getMaximum(String valueName) {
        return Collections.max(getValues(valueName));
    }

    public double getMinimum(String valueName) {
        try {
            return Collections.min(getValues(valueName));
        } catch (RuntimeException e) {
            logger.warn("Unable to get minimum value for key: " + valueName);
            throw e;
        }
    }

    public String getPlottableAverages(String[] yValueNames, String[]... xValueNames) {
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < yValueNames.length; i++) {
            b.append(getMean(yValueNames[i]));
            for (int j = 0; j < xValueNames.length; j++) {
                b.append(" ");
                b.append(getMean(xValueNames[j][i]));
            }
            b.append("\n");
        }
        return b.toString();
    }

    public String getPlottableAveragesAllLevels(String[] xValueNames, ResultType type,
            String... additionalCommands) {
        List<Integer> levels = getAllLevels(xValueNames[0]);
        return getPlottableAverages(levels, xValueNames, type, additionalCommands);
    }

    public String getPlottableAveragesAllLevels(String[] xValueNames, String indexColumn, ResultType type,
            String... additionalCommands) {
        List<Integer> levels = getAllLevels(indexColumn);
        return getPlottableAverages(levels, xValueNames, indexColumn, type, additionalCommands);
    }

    public List<Integer> getAllLevels(String xValueName) {
        return getAllLevels(xValueName, 2000);
    }

    public List<Integer> getAllLevels(String xValueName, int maxLevel) {
        List<Integer> levels = new LinkedList<Integer>();
        boolean goOn = true;
        boolean foundOne = false;
        for (int i = 0; i < maxLevel || goOn; i++) {
            String name = xValueName.replaceAll("<level>", "" + i);
            if (getValues(name).size() > 0) {
                levels.add(i);
                foundOne = true;
            } else if (foundOne) {
                goOn = false;
            }
        }
        return levels;
    }

    /** Deprecated: use getAllLevelIDsByPattern(..) instead! */
    @Deprecated
    public List<Integer> getAllLevelsByPattern(String pattern, int resultGroupNumber) {
        List<String> values = getAllValueNames(pattern);
        List<Integer> levels = new LinkedList<Integer>();
        for (String v : values) {
            v = v.replaceAll(pattern, "$" + resultGroupNumber);
            try {
                int lev = Integer.parseInt(v);
                if (!levels.contains(lev))
                    levels.add(lev);
            } catch (NumberFormatException e) {
                /* swallow */ }
        }
        return levels;
    }

    public List<String> getAllLevelIDsByPattern(String pattern, int resultGroupNumber) {
        List<String> values = getAllValueNames(pattern);
        List<String> levels = new LinkedList<String>();
        for (String v : values) {
            v = v.replaceAll(pattern, "$" + resultGroupNumber);
            if (!levels.contains(v))
                levels.add(v);
        }
        return levels;
    }

    public void createGnuplotMulti(List<?> levels, String[] xValueNames, String[] titles, ResultType type,
            String xLabel, String yLabel, String outFile, String... additionalCommands) throws Exception {
        if (additionalCommands == null)
            additionalCommands = new String[0];
        List<String> levelStrings = collUtil.toStringList(levels);
        LinkedList<String> temp = new LinkedList<String>(Arrays.asList(additionalCommands));
        temp.add(CMD_MULTI_LINE);
        additionalCommands = temp.toArray(new String[0]);
        createGnuplot("etc/createImageMulti.gnuplot", levelStrings, xValueNames, titles, type, xLabel, yLabel,
                outFile, additionalCommands);
    }

    public void createGnuplotHisto(List<?> levels, String[] xValueNames, String[] titles, ResultType type,
            String xLabel, String yLabel, String outFile, String... additionalCommands) throws Exception {
        if (additionalCommands == null)
            additionalCommands = new String[0];
        LinkedList<String> temp = new LinkedList<String>(Arrays.asList(additionalCommands));
        additionalCommands = temp.toArray(new String[0]);
        createGnuplot("etc/createImageHisto.gnuplot", levels, xValueNames, titles, type, xLabel, yLabel, outFile,
                additionalCommands);
    }

    public void createGnuplot(List<?> levels, String[] xValueNames, String[] titles, ResultType type, String xLabel,
            String yLabel, String outFile, String... additionalCommands) throws Exception {
        String file = Arrays.asList(additionalCommands).contains(GenericTestResult.CMD_MULTI_LINE)
                ? "etc/createImageMulti.gnuplot"
                : "etc/createImage.gnuplot";
        createGnuplot(file, levels, xValueNames, titles, type, xLabel, yLabel, outFile, additionalCommands);
    }

    public void createGnuplot(String[] xValueNames, String[] yValueNames, String[] titles, ResultType type,
            String xLabel, String yLabel, String outFile, String... additionalCommands) throws Exception {
        String plot = getPlottableAverages(yValueNames, xValueNames, additionalCommands);
        String file = Arrays.asList(additionalCommands).contains(GenericTestResult.CMD_MULTI_LINE)
                ? "etc/createImageMulti.gnuplot"
                : "etc/createImage.gnuplot";
        createGnuplot(file, xValueNames, yValueNames, null, plot, titles, type, xLabel, yLabel, outFile,
                additionalCommands);
    }

    public void createGnuplot(String fileName, List<?> levels, String[] xValueNames, String[] titles,
            ResultType type, String xLabel, String yLabel, String outFile, String... additionalCommands)
            throws Exception {
        String plot = getPlottableAverages(levels, xValueNames, type, additionalCommands);
        createGnuplot(fileName, xValueNames, null, levels, plot, titles, type, xLabel, yLabel, outFile,
                additionalCommands);
    }

    public void createGnuplot(String fileName, String[] xValueNames, String[] yValueNames, List<?> levels,
            String plot, String[] titles, ResultType type, String xLabel, String yLabel, String outFile,
            String... additionalCommands) throws Exception {

        List<String> xValueNamesNew = new LinkedList<String>();
        List<Integer> xValueNamesLengths = new LinkedList<Integer>();
        List<String> commandsList = new LinkedList<String>(Arrays.asList(additionalCommands));
        boolean hasCandleSticks = false;
        for (String s : xValueNames) {
            String[] split = s.split(":");
            xValueNamesLengths.add(split.length);
            hasCandleSticks |= split.length > 1;
            for (String sp : split) {
                xValueNamesNew.add(sp);
            }
        }
        if (hasCandleSticks) {
            if (levels == null) {
                plot = getPlottableAverages(yValueNames, xValueNames);
            } else {
                plot = getPlottableAverages(levels, xValueNames, type, additionalCommands);
            }
        }

        String gnuplotOriginal = null;
        if (new File(fileName).exists()) {
            gnuplotOriginal = ioUtil.readFile(fileName);
        } else {
            String file = fileName;
            if (file.contains("/"))
                file = file.substring(file.indexOf("/") + 1);
            Map<URL, String> resources = cpUtil.getSystemResources(file);
            if (resources.isEmpty()) {
                logger.warn("Unable to find system resource '" + file + "'");
            } else {
                gnuplotOriginal = resources.values().iterator().next();
            }
        }
        boolean multiline = commandsList.contains(CMD_MULTI_LINE);
        boolean drawLineCandle = commandsList.contains(CMD_DRAW_LINE_THROUGH_CANDLESTICKS);
        boolean multipleCandles = commandsList.contains(CMD_MULTIPLE_CANDLES_PER_XTICK);
        boolean multiAxes = commandsList.contains(CMD_MULTI_AXES);

        if (multiAxes) {
            for (int i = 1; i <= titles.length; i++) {
                commandsList.add("set y" + (i > 1 ? i : "") + "tics nomirror");
            }
        }

        String additional = "";
        for (String a : commandsList) {
            if (a.startsWith("##")) {
                // do not add
            } else if (a.startsWith("#")) {
                String left = a.substring(0, a.indexOf("="));
                String right = a.substring(a.indexOf("=") + 1);
                gnuplotOriginal = gnuplotOriginal.replaceAll(left, right);
            } else {
                additional += a + "\n";
            }
        }
        String gnuplot = gnuplotOriginal.replaceAll("#<extra>", additional);

        if (type == ResultType.REGRESSION) {
            gnuplot = gnuplot.replaceAll("#regression", "");
            gnuplot = gnuplot.replaceAll("\"gnuplot.values\" using 1:2 title '<title1>'",
                    "\"gnuplot.values\" using 1:2 title '<title1>', regrFunc(x) title 'Linear Regression' with lines");
            gnuplot = gnuplot.replaceAll("with linespoints ls 1", "");
        }

        if (commandsList.contains(CMD_FLIP_AXES)) {
            for (int i = 1; i <= titles.length; i++) {
                gnuplot = gnuplot.replaceAll("using 1:" + (i + 1), "using " + (i + 1) + ":1");
            }
            String tmp = xLabel;
            xLabel = yLabel;
            yLabel = tmp;
        }

        if (xLabel != null)
            gnuplot = gnuplot.replaceAll("<xlabel>", xLabel);
        if (yLabel != null)
            gnuplot = gnuplot.replaceAll("<ylabel>", yLabel);

        Map<Integer, String> fillStylePatterns = collUtil.asMap(0, "4").entry(1, "1").entry(2, "3").entry(3, "2")
                .entry(4, "3").entry(5, "4").entry(6, "5").entry(7, "7");

        for (int i = 1; i <= titles.length; i++) {
            gnuplot = gnuplot.replaceAll("#<do" + i + ">", "");
            if (hasCandleSticks || commandsList.contains(CMD_NO_LINES_JUST_POINTS)
                    || commandsList.contains(CMD_MULTI_AXES)) {

                int colIndexStart = 1 + getSublistSum(xValueNamesLengths, 0, i - 1) - xValueNamesLengths.get(i - 1)
                        + 1;
                int colIndexEnd = 1 + getSublistSum(xValueNamesLengths, 0, i - 1);
                String colIndexes = "";
                int maxCols = 4; /* required for candlesticks functionality */
                for (int j = colIndexStart; j <= colIndexEnd && j <= (maxCols + 1); j++) {
                    colIndexes += ":" + j;
                }
                String colIndexVariable = "(\\$1)";
                if (multipleCandles)
                    colIndexVariable = "(\\$1-0.5+" + ((double) i) * (1.0 / (double) titles.length) + ")";
                if (colIndexStart < colIndexEnd) {
                    String plotLine = "\"gnuplot.values\" using " + colIndexVariable + colIndexes + " title '<title"
                            + i + ">' with candlesticks whiskerbars ls " + i + " fs pattern "
                            + fillStylePatterns.get(i);

                    if (drawLineCandle) {
                        int idx = colIndexStart + 2;
                        if (xValueNamesLengths.get(i - 1) >= 5) {
                            idx = colIndexStart + 4;
                        }
                        plotLine += ", \"gnuplot.values\" using 1:" + idx + " title '' with lines ls " + i;
                    }

                    /* draw median line in boxplot/candlesticks */
                    if (xValueNamesLengths.get(i - 1) >= 5) {
                        int idx = (colIndexStart + 4);
                        plotLine += ", \"gnuplot.values\" using 1:" + idx + ":" + idx + ":" + idx + ":" + idx
                                + " with candlesticks lt -1 lw 2 notitle " + i;
                    }

                    if (multiAxes && i > 1) {
                        plotLine += " axes x1y" + i;
                    }

                    if (multiline) {
                        plotLine = "plot " + plotLine;
                    } else {
                        if (i < titles.length)
                            plotLine += ", \\\\";
                    }
                    gnuplot = gnuplot.replaceAll("#<plot" + i + ">.*\\n", plotLine + "\n");
                } else {
                    String plotLine = "\"gnuplot.values\" using 1" + colIndexes + " title '<title" + i
                            + ">' with linespoints ls " + i;
                    if (commandsList.contains(CMD_NO_LINES_JUST_POINTS)) {
                        plotLine = plotLine.replace("with linespoints", "with points");
                    }

                    if (multiAxes) {
                        plotLine += " axes x1y" + i;
                    }

                    if (multiline) {
                        plotLine = "plot " + plotLine;
                    } else {
                        if (i < titles.length)
                            plotLine += ", \\\\";
                    }
                    gnuplot = gnuplot.replaceAll("#<plot" + i + ">.*\\n", plotLine + "\n");
                }
            }
            gnuplot = gnuplot.replaceAll("#<plot" + i + ">", "");

            if (titles != null && titles.length >= i)
                gnuplot = gnuplot.replace("<title" + i + ">", titles[i - 1]);
        }
        for (int i = titles.length + 1; i < 10; i++) {
            gnuplot = gnuplot.replaceAll("#<do" + i + ">", "#");
        }
        System.out.println(gnuplot);

        ioUtil.saveFile("createImage.temp.gnuplot", gnuplot);
        ioUtil.saveFile("gnuplot.values", plot);

        Process gpProc = Runtime.getRuntime().exec("gnuplot createImage.temp.gnuplot");
        gpProc.waitFor();
        String output = ioUtil.readFile(gpProc.getInputStream());
        output += ioUtil.readFile(gpProc.getErrorStream());
        System.out.println("gnuplot output:\n------\n" + output);
        if (output != null && (output.contains("Not enough columns") || output.contains("no valid points"))) {
            System.out.println("---> Apparently, gnuplot reported an error. Input values were:");
            System.out.println(plot);
        }
        String fixbb = "etc/fixbb";
        String fixbbTmp = null;
        if (!new File(fixbb).exists()) {
            fixbb = "../" + fixbb;
            if (!new File(fixbb).exists()) {
                fixbb = "../" + fixbb;
            }
            if (!new File(fixbb).exists()) {
                Map<URL, String> resources = cpUtil.getSystemResources("fixbb");
                if (!resources.isEmpty()) {
                    fixbbTmp = UUID.randomUUID().toString();
                    ioUtil.saveFile(fixbbTmp, resources.values().iterator().next());
                    new File(fixbbTmp).setExecutable(true);
                    new File(fixbbTmp).deleteOnExit();
                    fixbb = "./" + fixbbTmp;
                }
            }
        }
        Runtime.getRuntime().exec(fixbb + " graph.eps").waitFor();
        if (fixbbTmp != null) {
            new File(fixbbTmp).delete();
        }
        if (outFile.endsWith(".pdf")) {
            Runtime.getRuntime().exec("epstopdf graph.eps").waitFor();
            new File("graph.pdf").renameTo(new File(outFile));
            new File("graph.pdf").delete();
        } else {
            new File("graph.eps").renameTo(new File(outFile));
        }
        new File("graph.eps").delete();
        new File("gnuplot.values").delete();
        new File("createImage.temp.gnuplot").delete();

    }

    private int getSublistSum(List<? extends Number> values, int fromIndexInclusive, int toIndexInclusive) {
        int sum = 0;
        for (int i = fromIndexInclusive; i <= toIndexInclusive; i++) {
            if (i >= 0 && i < values.size())
                sum += values.get(i).intValue();
        }
        return sum;
    }

    public String getPlottableAverages(List<?> levels, String[] xValueNames, ResultType type,
            String... additionalCommands) {
        return getPlottableAverages(levels, xValueNames, null, type, additionalCommands);
    }

    public String getPlottableAverages(List<?> levels, String[] xValueNames, String indexColumn, ResultType type,
            String... additionalCommands) {
        StringBuilder b = new StringBuilder();
        NumberFormat f = NumberFormat.getInstance(Locale.US);
        f.setMinimumFractionDigits(3);
        f.setMaximumFractionDigits(3);
        f.setGroupingUsed(false);

        List<String> commandsList = Arrays.asList(additionalCommands);

        for (int i = 0; i < levels.size(); i++) {
            String index = "" + levels.get(i);
            if (indexColumn != null) {
                index = "" + getMean(indexColumn.replaceAll("<level>", "" + levels.get(i)));
            }

            int modulo = commandsList.contains(CMD_ONLY_EVERY_2ND_XTICS) ? 2
                    : commandsList.contains(CMD_ONLY_EVERY_3RD_XTICS) ? 3 : 1;
            if (i % modulo == 0) {
                b.append(index);
            } else {
                b.append("_");
            }

            for (int j = 0; j < xValueNames.length; j++) {
                b.append("\t");
                String nameString = xValueNames[j];
                nameString = nameString.replaceAll("<level>", "" + levels.get(i));
                if (nameString.equals(xValueNames[j]))
                    nameString = nameString + levels.get(i);

                String[] actualNames = nameString.split(":");
                for (String name : actualNames) {

                    Double theValue = 0.0;
                    if (name.endsWith(".min")) {

                        theValue = getMinimum(name.substring(0, name.length() - ".min".length()));

                    } else if (name.endsWith(".max")) {

                        theValue = getMaximum(name.substring(0, name.length() - ".max".length()));

                    } else {
                        List<Double> values = getValues(name);
                        if (type == ResultType.MEAN) {
                            Number mean = getMean(values);
                            theValue = mean.doubleValue();
                        } else if (type == ResultType.THROUGHPUT) {
                            theValue = getThroughput(name);
                        }
                        if (values.size() <= 0) {
                            theValue = Double.NaN;
                        }
                    }
                    if (theValue > 1000000) {
                        b.append(theValue.longValue());
                    } else {
                        String val = f.format(theValue);
                        if ((theValue).isNaN()) {
                            //val = "0";
                            val = "NaN";
                        }
                        while (val.length() < 10)
                            val = " " + val;
                        b.append(val);
                    }

                }

            }
            b.append("\n");
        }
        return b.toString();
    }

    public static String[] getArray(String prefix, List<Integer> numbers) {
        String[] result = new String[numbers.size()];
        for (int i = 0; i < numbers.size(); i++) {
            result[i] = prefix + numbers.get(i);
        }
        return result;
    }

    public List<IterationResult> getIterations() {
        return iterations;
    }

    public void setIterations(List<IterationResult> iterations) {
        this.iterations = iterations;
    }

    public long getFinishTime() {
        return finishTime;
    }

    public void setFinishTime() {
        this.finishTime = System.currentTimeMillis();
    }

    public void setFinishTime(long finishTime) {
        this.finishTime = finishTime;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime() {
        this.startTime = System.currentTimeMillis();
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder();
        List<String> names = new LinkedList<String>();
        if (iterations.size() > 0) {
            IterationResult iter = iterations.get(0);
            for (Entry e : iter.getEntries()) {
                String name = e.name;
                if (!names.contains(name)) {
                    names.add(name);
                    b.append(name + ":\n");
                    b.append("\tTotal: " + getTotal(name) + "\n");
                    b.append("\tAmount: " + getAmount(name) + "\n");
                    b.append("\tMean: " + getMean(name) + "\n");
                    b.append("\tStd.Dev.: " + getStdDeviation(name) + "\n");
                }
            }
        }
        return b.toString();
    }

    public long getDuration() {
        return finishTime - startTime;
    }

    public List<Entry> searchEntries(String namePattern, String valuePattern) {
        List<Entry> result = new LinkedList<Entry>();
        for (Entry e : getEntriesByNamePattern(namePattern)) {
            if (e.value != null && e.value.toString().matches(valuePattern)) {
                result.add(e);
            }
        }
        return result;
    }

    public static GenericTestResult loadLast(String fileNamePattern) throws Exception {
        return loadLast(fileNamePattern, "<time>");
    }

    public static GenericTestResult loadLast(String fileNamePattern, String placeHolder) throws Exception {
        String dir = fileNamePattern.contains("/") ? fileNamePattern.substring(0, fileNamePattern.lastIndexOf("/"))
                : "./";
        String file = fileNamePattern.contains("/")
                ? fileNamePattern.substring(fileNamePattern.lastIndexOf("/") + 1)
                : fileNamePattern;
        List<Long> ids = new LinkedList<Long>();
        for (String f : new File(dir).list()) {
            String pattern = file.replace(placeHolder, "(.+)");
            Pattern p = Pattern.compile(pattern);
            Matcher m = p.matcher(f);
            if (m.matches()) {
                String id = m.group(1);
                try {
                    ids.add(Long.parseLong(id));
                } catch (Exception e) {
                    logger.warn("Ignoring ID '" + id + "', which cannot be parsed as Long.");
                }
            }
        }
        String id = ids.isEmpty() ? "" : ("" + Collections.max(ids));
        return load(fileNamePattern.replace(placeHolder, id));
    }

    public static GenericTestResult load(String file) throws Exception {
        XMLUtil xmlUtil = new XMLUtil();
        IOUtil ioUtil = new IOUtil();
        String content = ioUtil.readFile(new FileInputStream(file));
        Element e = xmlUtil.toElement(content);
        return xmlUtil.toJaxbObject(GenericTestResult.class, e);
    }

    public void saveOnShutdown(final String filePath) {
        saveOnShutdown(filePath, null);
    }

    public void saveOnShutdown(final String filePath, final Runnable runBefore) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                if (runBefore != null) {
                    runBefore.run();
                }
                save(filePath);
            }
        });
    }

    public boolean save(String filePath) {
        try {
            XMLUtil xmlUtil = new XMLUtil();
            String content = xmlUtil.toString(xmlUtil.toElement(this), true);
            ioUtil.saveFile(filePath, content);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public double getThroughput(String key) {
        double duration = getMean(key + "duration");
        double numResults = getValues(key).size();
        double resultsPerMS = numResults / duration;
        double resultsPerS = resultsPerMS * 1000.0;
        double resultsPerM = resultsPerS * 60.0;
        return resultsPerM;
    }

    public double getPercentile(String valueName, double p) {
        return getPercentile(getValues(valueName), p);
    }

    public double getPercentile(List<Double> values, double p) {
        Collections.sort(values);
        double size = values.size();
        double index = (size - 1.0) * p;
        return values.get((int) index);
    }

    public String getPlottableValuesBoxplot(List<Integer> levels, String... keyTemplates) {
        StringBuilder b = new StringBuilder();
        for (int l : levels) {
            b.append(l + "\t");
            for (String template : keyTemplates) {
                String key = template.replaceAll("<level>", "" + l);
                double min = getMinimum(key);
                double max = getMaximum(key);
                double p25 = getPercentile(key, 0.25);
                double p50 = getPercentile(key, 0.5);
                double p75 = getPercentile(key, 0.75);
                b.append(min + "\t" + p25 + "\t" + p50 + "\t" + p75 + "\t" + max + "\t");
            }
            b.append("\n");
        }
        return b.toString();
    }

    public List<Entry> getEntriesByName(String name) {
        List<Entry> result = new LinkedList<Entry>();
        for (IterationResult i : iterations) {
            for (Entry e : new LinkedList<Entry>(i.entries)) {
                if (e.getName().equals(name)) {
                    result.add(e);
                }
            }
        }
        return result;
    }

    public List<Entry> getEntriesByNamePattern(String namePattern) {
        List<Entry> result = new LinkedList<Entry>();
        for (IterationResult i : iterations) {
            for (Entry e : new LinkedList<Entry>(i.entries)) {
                if (e.getName().matches(namePattern)) {
                    result.add(e);
                }
            }
        }
        return result;
    }

    public void limitNumberOfEntries(String levelsEntryNamePattern, String valuesEntryNamePattern, int limit,
            EliminationMethod method) {
        List<Integer> levels = getAllLevels(levelsEntryNamePattern);
        int maxLevel = levels.size() + 1;
        int numValues = levels.size();
        if (numValues <= limit)
            return;
        int excess;
        if (method == EliminationMethod.CONSIDER_VALUE_DIFFERENCES) {
            do {
                // in a loop, determine the three entries (e1,e2,e3) with the smallest distance 
                // between e1 and e3 and then delete e2! This method assumes that the values are ORDERED!
                String levelEntryNameToRemove = null;
                double lowestDiffValue = Double.MAX_VALUE;
                for (int i = 0; i < levels.size() - 2; i++) {
                    String name1 = valuesEntryNamePattern.replaceAll("<level>", "" + levels.get(i));
                    String name2 = valuesEntryNamePattern.replaceAll("<level>", "" + levels.get(i + 2));
                    double value1 = getMean(name1);
                    double value2 = getMean(name2);
                    double diff = Math.abs(value2 - value1);
                    if (diff < lowestDiffValue) {
                        lowestDiffValue = diff;
                        levelEntryNameToRemove = levelsEntryNamePattern.replaceAll("<level>",
                                "" + levels.get(i + 1));
                    }
                }
                for (IterationResult i : iterations) {
                    for (Entry e : new LinkedList<Entry>(i.entries)) {
                        if (e.getName().equals(levelEntryNameToRemove)) {
                            i.entries.remove(e);
                        }
                    }
                }
                levels = getAllLevels(levelsEntryNamePattern, maxLevel);
                numValues = levels.size();
                excess = numValues - limit;
            } while (excess > 0);
        } else {
            throw new RuntimeException("Not yet implemented.");
        }
    }

    public void insertIntoLatexTemplate(String string, String outFile, String[] valueNames, List<Integer> levels)
            throws Exception {
        insertIntoLatexTemplate(string, new FileOutputStream(outFile), valueNames, levels, false);
    }

    public void insertIntoLatexTemplate(File templateFile, String outFile, String[] valueNames,
            List<Integer> levels, boolean doTTest) throws Exception {
        String template = ioUtil.readFile(new FileInputStream(templateFile));
        insertIntoLatexTemplate(template, new FileOutputStream(outFile), valueNames, levels, doTTest);
    }

    public void insertIntoLatexTemplate(File templateFile, String outFile) throws Exception {
        insertIntoLatexTemplate(templateFile, outFile, null);
    }

    public void insertIntoLatexTemplate(File templateFile, String outFile, String pattern) throws Exception {
        String template = ioUtil.readFile(new FileInputStream(templateFile));
        Pattern p = Pattern.compile("\\$([^\\$]+)\\$");
        Matcher m = p.matcher(template);
        List<String> fillIns = new LinkedList<String>();
        while (m.find()) {
            fillIns.add(m.group(1));
        }
        List<String> vNames = getAllValueNames(pattern);
        for (int i = 0; i < vNames.size(); i++) {
            boolean isContained = false;
            String vName = vNames.get(i);
            for (String s : fillIns) {
                if (s.startsWith(vName)) {
                    isContained = true;
                    break;
                }
            }
            if (!isContained)
                vNames.remove(i--);
        }
        //System.out.println("required variable names in template: " + vNames);
        insertIntoLatexTemplate(templateFile, outFile, vNames.toArray(new String[] {}), Arrays.asList(0), false);
    }

    public List<String> getAllValueNames() {
        return getAllValueNames(null);
    }

    public List<String> getAllValueNames(String pattern) {
        Pattern p = pattern != null ? Pattern.compile(pattern) : null;

        List<String> result = new LinkedList<String>();
        for (IterationResult i : iterations) {
            for (Entry e : i.getEntries()) {
                if (!result.contains(e.name)) {
                    if (p == null || p.matcher(e.name).matches())
                        result.add(e.name);
                }
            }
        }

        return result;
    }

    public String replace(String in, Map<String, String> searchReplace, int maxParallelReplacements) {

        if (searchReplace == null || searchReplace.isEmpty())
            return in;

        Map<String, String> thisSearchReplace = new HashMap<String, String>();
        int i = 0;
        for (String s : searchReplace.keySet()) {
            if ((i++) >= maxParallelReplacements)
                break;
            thisSearchReplace.put(s, searchReplace.get(s));
        }

        String patternString = "(" + StringUtils.join(thisSearchReplace.keySet(), "|") + ")";

        for (String s : thisSearchReplace.keySet())
            searchReplace.remove(s);

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(in);

        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, thisSearchReplace.get(matcher.group(1)));
        }
        matcher.appendTail(sb);

        in = sb.toString();

        if (searchReplace.size() > 0)
            return replace(in, searchReplace, maxParallelReplacements);

        return in;
    }

    public void insertIntoLatexTemplate(String templateContent, OutputStream out, String[] valueNames,
            List<Integer> levels, boolean doTTest) throws Exception {
        String content = templateContent;

        for (String name : valueNames) {
            for (int i : levels) {
                String theName = name.replaceAll("<level>", "" + i);
                String nameWithoutLevel = name.replaceAll("<level>", "");
                String nameInTemplate = theName;

                if (content.contains("$" + nameInTemplate + ".avg$")) {
                    double avg = getMean(theName);
                    content = content.replaceAll("\\$" + nameInTemplate + ".avg\\$", "" + f.format(avg));
                }
                if (content.contains("$" + nameInTemplate + ".min$")) {
                    double min = getMinimum(theName);
                    content = content.replaceAll("\\$" + nameInTemplate + ".min\\$", "" + f.format(min));
                }
                if (content.contains("$" + nameInTemplate + ".max$")) {
                    double max = getMaximum(theName);
                    content = content.replaceAll("\\$" + nameInTemplate + ".max\\$", "" + f.format(max));
                }
                if (content.contains("$" + nameInTemplate + ".avgAllLev$")) {
                    double avgAllLevels = getMean(name, levels);
                    content = content.replaceAll("\\$" + nameWithoutLevel + ".avgAllLev\\$",
                            "" + f.format(avgAllLevels));
                }
                if (content.contains("$" + nameInTemplate + ".stddev$")) {
                    double stddev = getStdDeviation(theName);
                    content = content.replaceAll("\\$" + nameInTemplate + ".stddev\\$", "" + f.format(stddev));
                }
                if (content.contains("$" + nameInTemplate + ".perct$")) {
                    double perct = getPercentage(name, valueNames, levels);
                    content = content.replaceAll("\\$" + nameInTemplate + ".perct\\$", "" + f.format(perct));
                }

                if (doTTest) {
                    for (String name1 : valueNames) {
                        String theName1 = name1.replaceAll("<level>", "" + i);
                        String nameInTemplate1 = name1.replaceAll("<level>", "");
                        if (!theName1.equals(nameInTemplate1))
                            nameInTemplate1 += "." + i;
                        double t = getTValue(getMean(theName), getMean(theName1), getSampleVariance(theName),
                                getSampleVariance(theName1), (int) getAmount(theName));
                        content = content.replaceAll(
                                "\\$" + nameInTemplate + "." + nameInTemplate1 + "." + i + ".t\\$",
                                "" + f.format(t));
                    }
                }
            }
        }

        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
        bw.write(content);
        bw.close();
    }

    private double getPercentage(String oneName, String[] allNames, List<Integer> levels) {
        double sum = 0;
        for (String a : allNames) {
            sum += getMean(a, levels);
        }
        double oneMean = getMean(oneName, levels);
        return (oneMean / sum) * 100.0;
    }

    private double getMean(String nameTemplate, List<Integer> levels) {
        double sum = 0;
        for (int l : levels) {
            String name = nameTemplate.replaceAll("<level>", "" + l);
            sum += getMean(name);
        }
        return sum / (double) levels.size();
    }

    protected double getPercentage(String nameTemplate, int i, List<Integer> levels) {
        double sum = 0;
        for (int l : levels) {
            String name = nameTemplate.replaceAll("<level>", "" + l);
            sum += getMean(name);
        }
        String name = nameTemplate.replaceAll("<level>", "" + i);
        return getMean(name) / sum;
    }

    public static double getTValue(double avgA, double avgB, double varianceA, double varianceB, int iterations) {
        double diff = avgA - avgB;
        double sum = (varianceA + varianceB) / (double) (iterations);
        return diff / Math.sqrt(sum);
    }

    public static double[] convert(Double[] in) {
        double[] out = new double[in.length];
        for (int i = 0; i < in.length; i++)
            out[i] = in[i];
        return out;
    }

    public static double[] convert(List<Double> in) {
        return convert(in.toArray(new Double[0]));
    }

    private static double getBarPosition(final double barWidth, final double spacing, int group,
            int positionInGroup) {
        if (group <= 0 && positionInGroup <= 0)
            return 0.5;
        if (positionInGroup >= 0) {
            double add = 0;
            // if(positionInGroup == 0)
            // add = barWidth;
            return add + barWidth + getBarPosition(barWidth, spacing, group, positionInGroup - 1);
        }
        if (group > 0) {
            int newPositionInGroup = 1;
            int newGroup = group - 1;
            if (newGroup <= 0)
                newPositionInGroup = 4;
            else if (newGroup == 1 || newGroup == 2)
                newPositionInGroup = 3;
            else if (newGroup > 2 && newGroup < 7)
                newPositionInGroup = 2;
            double add = 0;
            if (newGroup >= 4)
                add = -barWidth;
            return add + spacing + getBarPosition(barWidth, spacing, newGroup, newPositionInGroup);
        }
        return 0;
    }

    public static double getBarLabelPosition(final double barWidth, final double spacing, int group) {
        double min = getBarPosition(barWidth, spacing, group, 0);
        int position = 0;
        if (group <= 0)
            position = 4;
        else if (group >= 1 && group <= 2)
            position = 3;
        else if (group == 3)
            position = 2;
        else if (group > 3 && group < 7)
            position = 1;
        double max = getBarPosition(barWidth, spacing, group, position);
        return (max + min) / 2.0;
    }

    public String getPlottableAverages3D(List<Integer> levels, String[] keyTemplates, ResultType type,
            String... additionalCommands) {
        StringBuilder b = new StringBuilder();
        NumberFormat f = NumberFormat.getInstance(Locale.US);
        f.setMinimumFractionDigits(3);
        f.setMaximumFractionDigits(3);
        f.setGroupingUsed(false);
        for (int l : levels) {
            for (String t : keyTemplates) {
                String key = t.replaceAll("<level>", "" + l);
                Double val = 0.0;
                if (type == ResultType.THROUGHPUT)
                    val = getThroughput(key);
                else if (type == ResultType.MEAN)
                    val = getMean(key);
                if (val.isNaN())
                    val = 0.0;
                b.append(f.format(val));
                b.append("\n");
            }
            b.append("\n");
        }
        return b.toString();
    }

    @Deprecated
    public static void combineResults(String pattern, String... fileNames) throws Exception {
        XMLUtil xmlUtil = new XMLUtil();
        GenericTestResult result = new GenericTestResult();
        int i = 0;
        for (String filename : fileNames) {
            JAXBContext context = JAXBContext.newInstance(GenericTestResult.class);
            Unmarshaller unmarsh = context.createUnmarshaller();
            GenericTestResult temp = (GenericTestResult) unmarsh.unmarshal(new File(filename));
            String contents = xmlUtil.toString(xmlUtil.toElement(temp));
            contents = contents.replaceAll(pattern + "[0-9]+", pattern + (i++));
            temp = xmlUtil.toJaxbObject(GenericTestResult.class, xmlUtil.toElement(contents));
            result.getIterations().addAll(temp.getIterations());
        }
        String out = xmlUtil.toString(xmlUtil.toElement(result), true);
        System.out.println(out);
    }

    public void mergeWith(GenericTestResult temp) {
        while (getIterations().size() < temp.getIterations().size())
            newIteration();
        for (int i = 0; i < temp.getIterations().size(); i++) {
            IterationResult iter = temp.getIterations().get(i);
            getIterations().get(i).getEntries().addAll(iter.getEntries());
        }
    }

    public void mergeWith(Collection<GenericTestResult> temp) {
        for (GenericTestResult r : temp) {
            mergeWith(r);
        }
    }

    //   public static void main(String[] args) throws Exception {
    //
    //      if (args.length > 0 && args[0].equals("combine")) {
    //         combineResults(args[1], Arrays.copyOfRange(args, 2, args.length));
    //         return;
    //      }
    //
    //      String filename = "etc/performanceTestResults_PortfolioUnoptimized.xml";
    //      if (args.length > 0) {
    //         filename = args[0];
    //         if (!new File(filename).exists()) {
    //            filename = "etc/performanceTestResults_" + args[0] + ".xml";
    //         }
    //      } else
    //         args = new String[] { "Voting" };
    //      JAXBContext context = JAXBContext.newInstance(GenericTestResult.class);
    //      Unmarshaller unmarsh = context.createUnmarshaller();
    //      GenericTestResult result = (GenericTestResult) unmarsh
    //            .unmarshal(new File(filename));
    //
    //      List<Integer> levels = Arrays.asList(10, 30, 100, 250, 500);
    //      String[] valueNames = new String[] {};
    //      String out = null;
    //      ResultType type = ResultType.MEAN;
    //      if (args.length > 0 && args[0].contains("Booking")) {
    //         levels = Arrays
    //               .asList(10, 50, 100, 200, 500, 750/* , 1000, 1500, 2000 */);
    //         List<Integer> parallelities = Arrays.asList(1, 5, 10, 15, 30, 50);
    //         // System.out.println(result.getThroughput("s500h2c3r1p1st1"));
    //         // System.out.println(result.getThroughput("s500h2c3r1p5st1"));
    //         // System.out.println(result.getThroughput("s500h2c3r1p10st1"));
    //         // System.out.println(result.getThroughput("s500h2c3r1p15st1"));
    //         // System.out.println(result.getThroughput("s500h2c3r1p30st1"));
    //         // System.out.println(result.getThroughput("s500h2c3r1p50st1"));
    //         String template = "s<level>h2a30c3r1p<par>st<strategy>";
    //         List<String> names = new ArrayList<String>();
    //         for (int strategy = 0; strategy < 5; strategy++) {
    //            for (int par : parallelities) {
    //               String s = template;
    //               s = s.replaceAll("<strategy>", "" + strategy);
    //               s = s.replaceAll("<par>", "" + par);
    //               names.add(s);
    //            }
    //         }
    //         // out = result.getPlottableAverages3D(levels, names.toArray(new
    //         // String[]{}), ResultType.THROUGHPUT);
    //
    //         valueNames = names.toArray(new String[] {});
    //         if (args.length > 1 && !args[1].equals("3D")) {
    //
    //            int strategy = Integer.parseInt(args[1]);
    //            out = null;
    //            levels = Arrays.asList(1, 5, 10, 20, 30, 50, 75, 100); // parallelities
    //            valueNames = new String[] {
    //                  "s10h1a20c3r30p<level>st" + strategy,
    //                  "s50h1a20c3r30p<level>st" + strategy,
    //                  "s100h1a20c3r30p<level>st" + strategy,
    //                  "s200h1a20c3r30p<level>st" + strategy };
    //            type = ResultType.THROUGHPUT;
    //
    //         } else if (args.length > 1 && args[1].equals("3D")) {
    //            int strategy = 0;
    //            if (args.length > 2) {
    //               if (args.length > 2 && args[2].equals("aggregators")) {
    //                  parallelities = Arrays.asList(1, 5, 10, 15, 30, 50, /* */
    //                        75, 100);
    //                  strategy = 0;
    //                  template = "s200h2a<level>c3r1p<par>st" + strategy;
    //                  levels = Arrays.asList(1, 3, 5, /* */7, 10, 15/* */); // in
    //                                                            // this
    //                                                            // case:
    //                                                            // parallelity
    //                                                            // levels
    //                  names.clear();
    //                  for (int par : parallelities) {
    //                     String s = template;
    //                     s = s.replaceAll("<par>", "" + par);
    //                     names.add(s);
    //                  }
    //                  out = result.getPlottableAverages3D(levels, names
    //                        .toArray(new String[] {}),
    //                        ResultType.THROUGHPUT);
    //
    //               } else {
    //                  try {
    //                     strategy = Integer.parseInt(args[2]);
    //                  } catch (Exception e) {
    //                  }
    //                  levels = Arrays.asList(10, 50, 100, 200, 500/* , 750 */);
    //                  parallelities = Arrays.asList(1, 5, 10, 15, 30, 50, 75,
    //                        100);
    //                  template = "s<level>h1a20c3r1p<par>st" + strategy;
    //                  names.clear();
    //                  for (int par : parallelities) {
    //                     String s = template;
    //                     s = s.replaceAll("<par>", "" + par);
    //                     names.add(s);
    //                  }
    //                  out = result.getPlottableAverages3D(levels, names
    //                        .toArray(new String[] {}),
    //                        ResultType.THROUGHPUT);
    //
    //               }
    //            }
    //         } else if (args[0].equals("BookingNumAggregators")) {
    //            // result.eliminateXhighestValues = 2;
    //
    //            levels = Arrays.asList(1,/* 3, */5,/* 7, */10, 15, 20/* ,25,30 */); // number
    //                                                            // of
    //                                                            // deployed
    //                                                            // aggregators
    //            // levels = Arrays.asList(1, 25, 50, 100); // parallelity
    //
    //            // out = result.getPlottableValuesBoxplot(levels,
    //            // "s200h2a30c3r1p<level>st0", "s200h2a30c3r1p<level>st0");
    //            // out = result.getPlottableValuesBoxplot(levels,
    //            // "s200h2a<level>c3r1p1st0", "s200h2a<level>c3r1p50st0");
    //            out = result.getPlottableValuesBoxplot(levels,
    //                  "s50h2a<level>c3r1p25st0", "s50h2a<level>c3r1p50st0",
    //                  "s50h2a<level>c3r1p100st0");
    //         }
    //
    //      } else if (args.length > 0 && args[0].equals("Rendering")) {
    //         levels = Arrays.asList(50, 100, 300, 700, 1200, 2000);
    //         valueNames = new String[] { "s<level>h0c3r1", "s<level>h1c2r1",
    //               "s<level>h1c3r1", "s<level>h2c2r1", "s<level>h2c3r1" };
    //
    //      } else if (args.length > 0 && args[0].equals("Voting")) {
    //         levels = Arrays.asList(100, 200, 400, 700, 1000);
    //         valueNames = new String[] { "s<level>h0a15c3r100p1st0",
    //               "s<level>h1a15c2r100p1st0", "s<level>h1a15c3r100p1st0",
    //               "s<level>h2a15c2r100p1st0", "s<level>h2a15c3r100p1st0" };
    //         
    //         if (args.length > 1 && args[1].equals("memGnuplot")) {
    //            double barWidth = 0.3;
    //            double spacing = 0.5;
    //            String[] keys = new String[] { "s1000h2c3_m", "s1000h2c2_m",
    //                  "s1000h1c3_m", "s1000h1c2_m", "s1000h0c3_m" };
    //            out = "";
    //            // ("1" 0.675, "2" 1.635, "3" 2.595, "4" 3.555, "5" 4.515, "6"
    //            // 5.475, "7" 6.435, "8" 7.395, "9" 8.355, "10" 9.315, "11"
    //            // 10.275, "12" 11.235, "13" 12.195)
    //            out = "set xtics (";
    //            for (int i = 1; i <= 13; i++) {
    //               out += "\"" + i + "\" "
    //                     + getBarLabelPosition(barWidth, spacing, i - 1);
    //               if (i < 13)
    //                  out += ", ";
    //            }
    //            out += ")\n";
    //            out += "plot '-' with boxes lt 3 title \"13 Aggregators\", '-' with boxes fs pattern 5 lt 4 title \"7 Aggregators\", '-' title \"4 Aggregators\" with boxes fs pattern 6 lt 5, '-' title \"3 Aggregators\" with boxes fs pattern 10 lt 6, '-' title \"1 Aggregator\" with boxes fs pattern 9 lt 7\n";
    //            int count = 0;
    //            for (String key : keys) {
    //               for (int i = 1; i <= 13; i++) {
    //                  // double pos = 0.5 + count*spacing + (i-1)*barWidth;
    //                  double pos = getBarPosition(barWidth, spacing, i - 1,
    //                        count);
    //                  if ((count == 4 && i <= 1) || (count == 3 && i <= 3)
    //                        || (count == 2 && i <= 4)
    //                        || (count == 1 && i <= 7)
    //                        || (count == 0 && i <= 13)) {
    //                     out += pos + ", "
    //                           + (result.getMean(key + i) / 1000000.0);
    //                     out += "\n";
    //                  }
    //               }
    //               out += "e\n";
    //               count++;
    //            }
    //         } else if (args.length > 1 && args[1].equals("3D")) {
    //            Integer[] numsResults = { 100, 200, 400, 700, 1000 };
    //            String[] numsAggrs = { "s100h2c3r<level>", "s100h2c2r<level>",
    //                  "s100h1c3r<level>", "s100h1c2r<level>",
    //                  "s100h0c3r<level>" };
    //            out = result.getPlottableAverages3D(Arrays.asList(numsResults),
    //                  numsAggrs, ResultType.MEAN);
    //         }
    //      } else if (args.length > 0
    //            && (args[0].equals("PortfolioUnoptimized") || args[0]
    //                  .equals("PortfolioOptimized"))) {
    //         levels = Arrays.asList(1, 5, 10, 20, 30, 40, 50, 60);
    //         valueNames = new String[] { "s<level>h2a15c3r10p1st0",
    //               "s<level>h2a15c3r100p1st0", "s<level>h2a15c3r200p1st0" };
    //         result.eliminateXhighestValues = 1;
    //      }
    //
    //      if (out == null)
    //         out = result.getPlottableAverages(levels, valueNames, type);
    //      System.out.println(out);
    //
    //   }

}