org.ect.reo.simulation.views.SimulationViewResults.java Source code

Java tutorial

Introduction

Here is the source code for org.ect.reo.simulation.views.SimulationViewResults.java

Source

/*******************************************************************************
 * <copyright>
 * This file is part of the Extensible Coordination Tools (ECT).
 * Copyright (c) 2013 ECT developers. 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * </copyright>
 *******************************************************************************/
package org.ect.reo.simulation.views;

import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.ect.reo.Network;
import org.ect.reo.animation.Animation;
import org.ect.reo.animation.parts.NetworkComposite;
import org.ect.reo.simulation.simulator.Statistic;
import org.ect.reo.simulation.simulator.StatisticCategory;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.statistics.HistogramDataset;
import org.jfree.data.statistics.HistogramType;
import org.jfree.experimental.chart.swt.ChartComposite;

/**
 * Class to output all the results in the simulation view 
 */
public class SimulationViewResults {
    // Different types of statistics
    private static final int USAGE_PCT = 1;
    private static final int AVG_DURATION = 2;
    private static final int CALCULATED_PCT = 3;
    private static final int CALCULATED_DURATION = 4;

    // Some string formatters
    private static DecimalFormat integerFormat = new DecimalFormat("0");
    private static DecimalFormat decimalFormat = new DecimalFormat("0.0000");
    private static DecimalFormat ratioFormat = new DecimalFormat("0.00%");

    /**
     * Add the chart categories to the simulation view, it will use the statisticsCategories provided by the simulation view
     */
    public static void addChartCategories() {
        // Get the categories in a alphabetic order
        List<StatisticCategory> list = new ArrayList<StatisticCategory>();
        list.addAll(SimulationView.statisticCategories.values());
        Collections.sort(list);

        for (StatisticCategory category : list) {
            // Get all statistics from the category
            List<Statistic> statisticList = category.getAllStatistics(true);
            if ((statisticList != null) && (!statisticList.isEmpty())) {
                // If the user specified that he wants a chart for this category, create a tab for this statistic in the chartTabFolder
                if (category.isUseChart()) {
                    CTabFolder chartCategoryTabFolder = createTabFolder(SimulationView.chartTabFolder,
                            category.getDescription());
                    for (Statistic stat : category.getAllStatistics(true)) {
                        addChart(chartCategoryTabFolder, stat);
                    }
                }
                // If the user specified that he wants to see the result for this category, create a tab for this statistic in the resultTabFolder
                if (category.isUseResult()) {
                    CTabFolder resultCategoryTabFolder = createTabFolder(SimulationView.resultsTabFolder,
                            category.getDescription());
                    for (Statistic stat : category.getAllStatistics(true)) {
                        if (category.getDescription() == SimulationView.COL_STATKEY) {
                            addResult(resultCategoryTabFolder, stat, category.getDescription(), true);
                        } else {
                            addResult(resultCategoryTabFolder, stat, category.getDescription(), false);
                        }
                    }
                }
            }
        }
    }

    private static CTabFolder createTabFolder(CTabFolder tabFolder, String description) {
        // Create a tab folder with the provided description into the specified tabFolder
        CTabItem item = new CTabItem(tabFolder, SWT.NONE);
        item.setText((description.length() > 20) ? description.substring(0, 20) : description);

        CTabFolder result = new CTabFolder(tabFolder, SWT.NONE);
        result.setBorderVisible(true);
        result.setLayoutData(new GridData(GridData.FILL_BOTH));
        result.setSimple(false);

        item.setControl(result);

        return result;
    }

    private static void addChart(CTabFolder tabFolder, Statistic statistic) {
        // Add the chart to the specified tabFolder      
        JFreeChart chart = statistic.getChart();
        if (chart != null) {
            CTabItem item = new CTabItem(tabFolder, SWT.NONE);
            String description = statistic.getDescription();
            item.setText((description.length() > 20) ? description.substring(0, 20) : description);
            ChartComposite chartComposite = new ChartComposite(tabFolder, SWT.NONE, chart,
                    tabFolder.getBounds().width, tabFolder.getBounds().height, 200, 200, 1200, 768, true, true,
                    true, true, true, true);
            chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
            item.setControl(chartComposite);
        }
    }

    public static void addResult(CTabFolder tabFolder, Statistic statistic, String categoryDescription,
            boolean colouringResult) {
        // Add the statistic to the tabFolder. If colouringResult is true, we have to do some extra things.
        CTabItem item = new CTabItem(tabFolder, SWT.NONE);
        String description = statistic.getDescription();
        item.setText((description.length() > 20) ? description.substring(0, 20) : description);

        // Create a horizontal sashForm, in this sashForm the left part will be used for mean, sd, etc.
        // The right part of the sashForm will be used to display the results in every batch (which is used to calculate the mean, sd, etc)
        SashForm sashForm = new SashForm(tabFolder, SWT.HORIZONTAL);

        SashForm verticalSashForm = new SashForm(sashForm, SWT.VERTICAL);

        // Create a table for the calculated results (Mean, sd)
        Table table = new Table(verticalSashForm, SWT.BORDER | SWT.MULTI);
        table.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        TableColumn[] column = new TableColumn[2];
        column[0] = new TableColumn(table, SWT.NONE);
        column[0].setText("Statistic");

        column[1] = new TableColumn(table, SWT.NONE);
        column[1].setText("Value");

        // Fill these calculated results
        fillCalculatedResult(statistic, table, categoryDescription);

        for (int i = 0; i < column.length; i++) {
            column[i].pack();
        }

        if (colouringResult) {
            CTabFolder colTabFolder = new CTabFolder(verticalSashForm, SWT.NONE);
            colTabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
            colTabFolder.setSimple(false);

            CTabItem tabItem = new CTabItem(colTabFolder, SWT.NONE);
            tabItem.setText("Colouring");

            // If we are generating a colouring result, we want to display the connector with the corresponding colouring in the bottom left
            // part of the result tab. Also add a line to the colouring file with the colouring and the number it has got.
            NetworkComposite comp = new NetworkComposite(colTabFolder, SWT.BORDER);
            comp.setNetwork(new Network(SimulationView.connector));
            if (statistic.getState() != null) {
                comp.setAnimation((Animation) statistic.getState());
                try {
                    SimulationView.colWriter
                            .append(statistic.getDescription() + ", " + (Animation) statistic.getState() + '\n');
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            comp.setLayoutData(new GridData(GridData.FILL_BOTH));
            tabItem.setControl(comp);

            CTabItem tabItem2 = new CTabItem(colTabFolder, SWT.NONE);
            tabItem2.setText("Histogram");

            ChartComposite chartComposite = new ChartComposite(colTabFolder, SWT.NONE,
                    createHistogram(statistic, colTabFolder));
            chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
            tabItem2.setControl(chartComposite);

            colTabFolder.setSelection(0);
        } else {
            ChartComposite chartComposite = new ChartComposite(verticalSashForm, SWT.NONE,
                    createHistogram(statistic, verticalSashForm));
            chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
        }

        // Create a table for the results for every batch.
        Table batchTable = new Table(sashForm, SWT.BORDER | SWT.MULTI);
        batchTable.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
        batchTable.setHeaderVisible(true);
        batchTable.setLinesVisible(true);
        TableColumn[] batchColumn = new TableColumn[3];
        batchColumn[0] = new TableColumn(batchTable, SWT.NONE);
        batchColumn[0].setText("Batch");

        batchColumn[1] = new TableColumn(batchTable, SWT.NONE);
        batchColumn[1].setText("Value");

        batchColumn[2] = new TableColumn(batchTable, SWT.NONE);
        batchColumn[2].setText("Observations");

        // Fill the results
        fillBatchResult(statistic, batchTable);

        for (int i = 0; i < batchColumn.length; i++) {
            batchColumn[i].pack();
        }
        item.setControl(sashForm);
    }

    private static JFreeChart createHistogram(Statistic statistic, Composite composite) {
        HistogramDataset dataset = new HistogramDataset();
        dataset.setType(HistogramType.RELATIVE_FREQUENCY);
        int numOfBatches = Integer.parseInt(SimulationViewOptions.batchNumberText.getText());
        double[] values = new double[numOfBatches];

        for (int i = 0; i < numOfBatches; i++) {
            values[i] = statistic.getStatisticValue(i);
        }

        try {
            dataset.addSeries("Histogram of batch values", values,
                    (int) Math.ceil(Math.log(numOfBatches) / Math.log(2) + 1));
            return ChartFactory.createHistogram("Batch results", "Value", "Relative frequency", dataset,
                    PlotOrientation.VERTICAL, false, true, false);
        } catch (Throwable t) {
            return null;
        }
    }

    private static void fillCalculatedResult(Statistic statistic, Table table, String categoryDescription) {
        try {
            // Add the calculated results of this statistic to the result output file.
            FileWriter resultWriter = SimulationView.resultWriter;
            resultWriter.append(categoryDescription + "[" + statistic.getDescription() + "], ");

            table.setRedraw(false);

            // Add all calculated results to the table
            TableItem item = new TableItem(table, SWT.NONE);
            item.setText(0, "Mean");
            double mean = statistic.getMean();
            double result = mean;
            item.setText(1, formatNumber(result, statistic));
            resultWriter.append(result + ", ");

            item = new TableItem(table, SWT.NONE);
            result = statistic.getMeanCount();
            item.setText(new String[] { "Observations per batch", integerFormat.format(result) });
            resultWriter.append(result + ", ");

            item = new TableItem(table, SWT.NONE);
            result = statistic.getSd();
            item.setText(new String[] { "Standard deviation", decimalFormat.format(result) });
            resultWriter.append(result + ", ");

            item = new TableItem(table, SWT.NONE);
            result = (mean == 0) ? Double.NaN : statistic.getSd() / mean;
            item.setText(new String[] { "Coefficient of variation", decimalFormat.format(result) });
            resultWriter.append(result + ", ");

            item = new TableItem(table, SWT.NONE);
            item.setText(0, "Interval");
            double lowBound = statistic.getMean() - statistic.getConfidence();
            double highBound = statistic.getMean() + statistic.getConfidence();
            item.setText(1,
                    "[" + formatNumber(lowBound, statistic) + ", " + formatNumber(highBound, statistic) + "]");
            resultWriter.append(lowBound + ", ");
            resultWriter.append(Double.toString(highBound) + '\n');

            table.setRedraw(true);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void fillBatchResult(Statistic statistic, Table table) {
        // Add the statistic value for every batch to the table. The value will be formatted based on the statistic type.
        table.setRedraw(false);
        for (int i = 0; i < Integer.parseInt(SimulationViewOptions.batchNumberText.getText()); i++) {
            TableItem item = new TableItem(table, SWT.NONE);
            item.setText(
                    new String[] { Integer.toString(i + 1), formatNumber(statistic.getStatisticValue(i), statistic),
                            Integer.toString(statistic.getCount(i)) });
        }

        table.setRedraw(true);
    }

    private static String formatNumber(double number, Statistic statistic) {
        // format the number of the statistic based on the type of statistic
        switch (statistic.getType()) {
        case USAGE_PCT:
            return ratioFormat.format(number);
        case AVG_DURATION:
            return decimalFormat.format(number);
        case CALCULATED_PCT:
            return ratioFormat.format(number);
        case CALCULATED_DURATION:
            return decimalFormat.format(number);
        default:
            return decimalFormat.format(number);
        }
    }
}