com.vgi.mafscaling.VECalc.java Source code

Java tutorial

Introduction

Here is the source code for com.vgi.mafscaling.VECalc.java

Source

/*
* Open-Source tuning tools
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package com.vgi.mafscaling;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.Format;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.ResourceBundle;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardXYSeriesLabelGenerator;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;
import org.jfree.util.ShapeUtilities;

public class VECalc extends ACompCalc {
    private static final long serialVersionUID = -6288885401403089256L;
    private static final Logger logger = Logger.getLogger(VECalc.class);

    class LogData {
        public double rpm = 0;
        public double mp = 0;
        public double iat = 0;
        public double afr = 0;
        public double maf = 0;
        public double ffb = 0;
        public double sd = 0;
        public double sderr = 0;
        public double afrerr = 0;
    }

    private static final String xAxisName = "RPM";
    private static final String yAxisName = "Estimated VE";
    private int clValue = Config.getVEClOlStatusValue();
    private int afrRowOffset = Config.getWBO2RowOffset();
    private int thrtlMaxChange = Config.getVEThrottleChangeMaxValue();
    private int minCellHitCount = Config.getVEMinCellHitCount();
    private double thrtlMin = Config.getVEThrottleMinimumValue();
    private double afrMax = Config.getVEOlAfrMaximumValue();
    private double afrMin = Config.getVEAfrMinimumValue();
    private double rpmMin = Config.getVERPMMinimumValue();
    private double ffbMax = Config.getFFBMaximumValue();
    private double ffbMin = Config.getFFBMinimumValue();
    private double mpMin = Config.getVEMPMinimumValue();
    private double iatMax = Config.getVEIatMaximumValue();
    private boolean isOl = Config.veOpenLoop();
    private int corrApplied = Config.getVECorrectionAppliedValue();
    private int logClOlStatusColIdx = -1;
    private int logThrottleAngleColIdx = -1;
    private int logRpmColIdx = -1;
    private int logMpColIdx = -1;
    private int logIatColIdx = -1;
    private int logWbAfrColIdx = -1;
    private int logStockAfrColIdx = -1;
    private int logAfLearningColIdx = -1;
    private int logAfCorrectionColIdx = -1;
    private int logMafColIdx = -1;
    private int logFfbColIdx = -1;
    private int logSdColIdx = -1;

    private String[] logColumns = new String[] { "RPM", "IAT", "MP", "FFB", "AFR", "MAF", "VE" };
    private JComboBox<String> sdType = null;
    private JComboBox<String> mpType = null;
    private JComboBox<String> dataType = null;
    private ArrayList<Double> trims = new ArrayList<Double>();
    private HashMap<Double, HashMap<Double, ArrayList<LogData>>> xData = null;

    public VECalc(int tabPlacement) {
        super(tabPlacement);
        origTableName = "Current VE table";
        newTableName = "New VE table";
        corrTableName = "Error % table";
        corrCountTableName = "Error % Count table";
        x3dAxisName = "MP";
        y3dAxisName = "RPM";
        z3dAxisName = "Avg Error %";
        initialize(logColumns);
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // DATA TAB
    //////////////////////////////////////////////////////////////////////////////////////

    protected void createControlPanel(JPanel dataPanel) {
        JPanel cntlPanel = new JPanel();
        GridBagConstraints gbl_ctrlPanel = new GridBagConstraints();
        gbl_ctrlPanel.insets = insets3;
        gbl_ctrlPanel.anchor = GridBagConstraints.NORTH;
        gbl_ctrlPanel.fill = GridBagConstraints.HORIZONTAL;
        gbl_ctrlPanel.gridx = 0;
        gbl_ctrlPanel.gridy = 0;
        gbl_ctrlPanel.weightx = 1.0;
        gbl_ctrlPanel.gridwidth = 2;
        dataPanel.add(cntlPanel, gbl_ctrlPanel);

        GridBagLayout gbl_cntlPanel = new GridBagLayout();
        gbl_cntlPanel.columnWidths = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        gbl_cntlPanel.rowHeights = new int[] { 0 };
        gbl_cntlPanel.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                1.0 };
        gbl_cntlPanel.rowWeights = new double[] { 0 };
        cntlPanel.setLayout(gbl_cntlPanel);

        addButton(cntlPanel, 0, "Load Log", "loadlog", GridBagConstraints.WEST);
        addButton(cntlPanel, 1, "Clear SD Data", "clearorig", GridBagConstraints.WEST);
        addButton(cntlPanel, 2, "Clear Run Data", "clearlog", GridBagConstraints.WEST);
        addButton(cntlPanel, 3, "Clear All", "clearall", GridBagConstraints.WEST);
        addLabel(cntlPanel, 4, "SD");
        sdType = addComboBox(cntlPanel, 5, new String[] { "RR SD", "Cobb SD" });
        addLabel(cntlPanel, 6, "MP");
        mpType = addComboBox(cntlPanel, 7,
                new String[] { "Torr/mmHG Abs", "Torr/mmHG Rel Sea Lvl", "Psi Abs", "Psi Rel Sea Lvl" });
        addLabel(cntlPanel, 8, "Run");
        dataType = addComboBox(cntlPanel, 9, new String[] { "MAF Builder", "AFR Tuner" });
        addCheckBox(cntlPanel, 10, "Hide Log Table", "hidelogtable");
        compareTableCheckBox = addCheckBox(cntlPanel, 11, "Compare Tables", "comparetables");
        addButton(cntlPanel, 12, "GO", "go", GridBagConstraints.EAST);
    }

    protected void formatTable(JTable table) {
        if (table == corrCountTable) {
            Format[][] formatMatrix = { { new DecimalFormat("#"), new DecimalFormat("0.00") },
                    { new DecimalFormat("#"), new DecimalFormat("#") } };
            NumberFormatRenderer renderer = (NumberFormatRenderer) table.getDefaultRenderer(Object.class);
            renderer.setFormats(formatMatrix);
        } else {
            Format[][] formatMatrix = { { new DecimalFormat("#"), new DecimalFormat("0.00") } };
            NumberFormatRenderer renderer = (NumberFormatRenderer) table.getDefaultRenderer(Object.class);
            renderer.setFormats(formatMatrix);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // CREATE CHART TAB
    //////////////////////////////////////////////////////////////////////////////////////

    protected void createGraghTab() {
        JPanel plotPanel = new JPanel();
        add(plotPanel, "<html><div style='text-align: center;'>C<br>h<br>a<br>r<br>t</div></html>");

        GridBagLayout gbl_plotPanel = new GridBagLayout();
        gbl_plotPanel.columnWidths = new int[] { 0 };
        gbl_plotPanel.rowHeights = new int[] { 0, 0 };
        gbl_plotPanel.columnWeights = new double[] { 1.0 };
        gbl_plotPanel.rowWeights = new double[] { 0.0, 1.0 };
        plotPanel.setLayout(gbl_plotPanel);

        JPanel cntlPanel = new JPanel();
        GridBagConstraints gbl_ctrlPanel = new GridBagConstraints();
        gbl_ctrlPanel.insets = new Insets(3, 3, 3, 3);
        gbl_ctrlPanel.anchor = GridBagConstraints.NORTH;
        gbl_ctrlPanel.weightx = 1.0;
        gbl_ctrlPanel.fill = GridBagConstraints.HORIZONTAL;
        gbl_ctrlPanel.gridx = 0;
        gbl_ctrlPanel.gridy = 0;
        plotPanel.add(cntlPanel, gbl_ctrlPanel);

        GridBagLayout gbl_cntlPanel = new GridBagLayout();
        gbl_cntlPanel.columnWidths = new int[] { 0, 0 };
        gbl_cntlPanel.rowHeights = new int[] { 0, 0 };
        gbl_cntlPanel.columnWeights = new double[] { 0.0, 1.0 };
        gbl_cntlPanel.rowWeights = new double[] { 0 };
        cntlPanel.setLayout(gbl_cntlPanel);

        createChart(plotPanel, xAxisName, yAxisName);
    }

    protected void createChart(JPanel plotPanel, String xAxisName, String yAxisName) {
        JFreeChart chart = ChartFactory.createScatterPlot(null, null, null, null, PlotOrientation.VERTICAL, false,
                true, false);
        chart.setBorderVisible(true);

        chartPanel = new ChartPanel(chart, true, true, true, true, true);
        chartPanel.setAutoscrolls(true);
        chartPanel.setMouseZoomable(false);

        GridBagConstraints gbl_chartPanel = new GridBagConstraints();
        gbl_chartPanel.anchor = GridBagConstraints.CENTER;
        gbl_chartPanel.insets = new Insets(3, 3, 3, 3);
        gbl_chartPanel.weightx = 1.0;
        gbl_chartPanel.weighty = 1.0;
        gbl_chartPanel.fill = GridBagConstraints.BOTH;
        gbl_chartPanel.gridx = 0;
        gbl_chartPanel.gridy = 1;
        plotPanel.add(chartPanel, gbl_chartPanel);

        XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer();
        lineRenderer.setUseFillPaint(true);
        lineRenderer.setBaseToolTipGenerator(
                new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
                        new DecimalFormat("0.00"), new DecimalFormat("0.00")));

        Stroke stroke = new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, null, 0.0f);
        lineRenderer.setSeriesStroke(0, stroke);
        lineRenderer.setSeriesPaint(0, Color.RED);
        lineRenderer.setSeriesShape(0, ShapeUtilities.createDiamond((float) 2.5));

        lineRenderer.setLegendItemLabelGenerator(new StandardXYSeriesLabelGenerator() {
            private static final long serialVersionUID = 7593430826693873496L;

            public String generateLabel(XYDataset dataset, int series) {
                XYSeries xys = ((XYSeriesCollection) dataset).getSeries(series);
                return xys.getDescription();
            }
        });

        NumberAxis xAxis = new NumberAxis(xAxisName);
        xAxis.setAutoRangeIncludesZero(false);
        NumberAxis yAxis = new NumberAxis(yAxisName);
        yAxis.setAutoRangeIncludesZero(false);

        XYSeriesCollection lineDataset = new XYSeriesCollection();

        XYPlot plot = chart.getXYPlot();
        plot.setRangePannable(true);
        plot.setDomainPannable(true);
        plot.setDomainGridlinePaint(Color.DARK_GRAY);
        plot.setRangeGridlinePaint(Color.DARK_GRAY);
        plot.setBackgroundPaint(new Color(224, 224, 224));

        plot.setDataset(0, lineDataset);
        plot.setRenderer(0, lineRenderer);
        plot.setDomainAxis(0, xAxis);
        plot.setRangeAxis(0, yAxis);
        plot.mapDatasetToDomainAxis(0, 0);
        plot.mapDatasetToRangeAxis(0, 0);

        LegendTitle legend = new LegendTitle(plot.getRenderer());
        legend.setItemFont(new Font("Arial", 0, 10));
        legend.setPosition(RectangleEdge.TOP);
        chart.addLegend(legend);
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // CREATE USAGE TAB
    //////////////////////////////////////////////////////////////////////////////////////

    protected String usage() {
        ResourceBundle bundle;
        bundle = ResourceBundle.getBundle("com.vgi.mafscaling.ve_calc");
        return bundle.getString("usage");
    }

    //////////////////////////////////////////////////////////////////////////////////////
    // COMMOMN ACTIONS RELATED FUNCTIONS
    //////////////////////////////////////////////////////////////////////////////////////

    private boolean getColumnsFilters(String[] elements) {
        boolean ret = true;
        ArrayList<String> columns = new ArrayList<String>(Arrays.asList(elements));
        String logClOlStatusColName = Config.getClOlStatusColumnName();
        String logThrottleAngleColName = Config.getThrottleAngleColumnName();
        String logFfbColName = Config.getFinalFuelingBaseColumnName();
        String logSdColName = Config.getVEFlowColumnName();
        String logWbAfrColName = Config.getWidebandAfrColumnName();
        String logStockAfrColName = Config.getAfrColumnName();
        String logAfLearningColName = Config.getAfLearningColumnName();
        String logAfCorrectionColName = Config.getAfCorrectionColumnName();
        String logRpmColName = Config.getRpmColumnName();
        String logMafColName = Config.getMassAirflowColumnName();
        String logIatColName = Config.getIatColumnName();
        String logMpColName = Config.getMpColumnName();
        isOl = Config.veOpenLoop();
        logClOlStatusColIdx = columns.indexOf(logClOlStatusColName);
        logThrottleAngleColIdx = columns.indexOf(logThrottleAngleColName);
        logFfbColIdx = columns.indexOf(logFfbColName);
        logSdColIdx = columns.indexOf(logSdColName);
        logWbAfrColIdx = columns.indexOf(logWbAfrColName);
        logStockAfrColIdx = columns.indexOf(logStockAfrColName);
        logAfLearningColIdx = columns.indexOf(logAfLearningColName);
        logAfCorrectionColIdx = columns.indexOf(logAfCorrectionColName);
        logRpmColIdx = columns.indexOf(logRpmColName);
        logMafColIdx = columns.indexOf(logMafColName);
        logIatColIdx = columns.indexOf(logIatColName);
        logMpColIdx = columns.indexOf(logMpColName);
        if (logThrottleAngleColIdx == -1) {
            Config.setThrottleAngleColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logFfbColIdx == -1) {
            Config.setFinalFuelingBaseColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logSdColIdx == -1) {
            Config.setVEFlowColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logWbAfrColIdx == -1 && isOl) {
            Config.setWidebandAfrColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logStockAfrColIdx == -1 && !isOl) {
            Config.setAfrColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logAfLearningColIdx == -1 && !isOl) {
            Config.setAfLearningColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logAfCorrectionColIdx == -1 && !isOl) {
            Config.setAfCorrectionColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logRpmColIdx == -1) {
            Config.setRpmColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logMafColIdx == -1) {
            Config.setMassAirflowColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logMpColIdx == -1) {
            Config.setMpColumnName(Config.NO_NAME);
            ret = false;
        }
        if (logIatColIdx == -1) {
            Config.setIatColumnName(Config.NO_NAME);
            ret = false;
        }
        clValue = Config.getVEClOlStatusValue();
        rpmMin = Config.getVERPMMinimumValue();
        mpMin = Config.getVEMPMinimumValue();
        iatMax = Config.getVEIatMaximumValue();
        ffbMax = Config.getFFBMaximumValue();
        ffbMin = Config.getFFBMinimumValue();
        thrtlMaxChange = Config.getVEThrottleChangeMaxValue();
        minCellHitCount = Config.getVEMinCellHitCount();
        thrtlMin = Config.getVEThrottleMinimumValue();
        afrMax = (isOl ? Config.getVEOlAfrMaximumValue() : Config.getVEClAfrMaximumValue());
        afrMin = Config.getVEAfrMinimumValue();
        afrRowOffset = Config.getWBO2RowOffset();
        corrApplied = Config.getVECorrectionAppliedValue();
        return ret;
    }

    protected void loadLogFile() {
        fileChooser.setMultiSelectionEnabled(true);
        if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this))
            return;
        File[] files = fileChooser.getSelectedFiles();
        for (File file : files) {
            BufferedReader br = null;
            ArrayDeque<String[]> buffer = new ArrayDeque<String[]>();
            try {
                br = new BufferedReader(new FileReader(file.getAbsoluteFile()));
                String line = br.readLine();
                if (line != null) {
                    String[] elements = line.split("(\\s*)?,(\\s*)?", -1);
                    getColumnsFilters(elements);

                    boolean resetColumns = false;
                    if (logThrottleAngleColIdx >= 0 || logFfbColIdx >= 0 || logSdColIdx >= 0
                            || (logWbAfrColIdx >= 0 && isOl) || (logStockAfrColIdx >= 0 && !isOl)
                            || (logAfLearningColIdx >= 0 && !isOl) || (logAfCorrectionColIdx >= 0 && !isOl)
                            || logRpmColIdx >= 0 || logMafColIdx >= 0 || logIatColIdx >= 0 || logMpColIdx >= 0) {
                        if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null,
                                "Would you like to reset column names or filter values?", "Columns/Filters Reset",
                                JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE))
                            resetColumns = true;
                    }

                    if (resetColumns || logThrottleAngleColIdx < 0 || logFfbColIdx < 0 || logSdColIdx < 0
                            || (logWbAfrColIdx < 0 && isOl) || (logStockAfrColIdx < 0 && !isOl)
                            || (logAfLearningColIdx < 0 && !isOl) || (logAfCorrectionColIdx < 0 && !isOl)
                            || logRpmColIdx < 0 || logMafColIdx < 0 || logIatColIdx < 0 || logMpColIdx < 0) {
                        ColumnsFiltersSelection selectionWindow = new VEColumnsFiltersSelection(false);
                        if (!selectionWindow.getUserSettings(elements) || !getColumnsFilters(elements))
                            return;
                    }

                    if (logClOlStatusColIdx == -1)
                        clValue = -1;

                    String[] flds;
                    String[] afrflds;
                    boolean removed = false;
                    int i = 2;
                    int clol = -1;
                    int row = getLogTableEmptyRow();
                    double thrtlMaxChange2 = thrtlMaxChange + thrtlMaxChange / 2.0;
                    double throttle = 0;
                    double pThrottle = 0;
                    double ppThrottle = 0;
                    double afr = 0;
                    double rpm;
                    double ffb;
                    double iat;
                    clearRunTables();
                    setCursor(new Cursor(Cursor.WAIT_CURSOR));
                    for (int k = 0; k <= afrRowOffset && line != null; ++k) {
                        line = br.readLine();
                        if (line != null)
                            buffer.addFirst(line.split(",", -1));
                    }
                    try {
                        while (line != null && buffer.size() > afrRowOffset) {
                            afrflds = buffer.getFirst();
                            flds = buffer.removeLast();
                            line = br.readLine();
                            if (line != null)
                                buffer.addFirst(line.split(",", -1));
                            ppThrottle = pThrottle;
                            pThrottle = throttle;
                            throttle = Double.valueOf(flds[logThrottleAngleColIdx]);
                            try {
                                if (row > 0 && Math.abs(pThrottle - throttle) > thrtlMaxChange) {
                                    if (!removed)
                                        Utils.removeRow(row--, logDataTable);
                                    removed = true;
                                } else if (row <= 0 || Math.abs(ppThrottle - throttle) <= thrtlMaxChange2) {
                                    // Filters
                                    afr = (isOl ? Double.valueOf(afrflds[logWbAfrColIdx])
                                            : Double.valueOf(afrflds[logStockAfrColIdx]));
                                    rpm = Double.valueOf(flds[logRpmColIdx]);
                                    ffb = Double.valueOf(flds[logFfbColIdx]);
                                    iat = Double.valueOf(flds[logIatColIdx]);
                                    if (clValue != -1)
                                        clol = Integer.valueOf(flds[logClOlStatusColIdx]);
                                    boolean flag = isOl ? ((afr <= afrMax || throttle >= thrtlMin) && afr <= afrMax)
                                            : (afrMin <= afr);
                                    if (flag && clol == clValue && rpmMin <= rpm && ffbMin <= ffb && ffb <= ffbMax
                                            && iat <= iatMax) {
                                        removed = false;
                                        if (!isOl)
                                            trims.add(Double.valueOf(flds[logAfLearningColIdx])
                                                    + Double.valueOf(flds[logAfCorrectionColIdx]));
                                        Utils.ensureRowCount(row + 1, logDataTable);
                                        logDataTable.setValueAt(rpm, row, 0);
                                        logDataTable.setValueAt(iat, row, 1);
                                        logDataTable.setValueAt(Double.valueOf(flds[logMpColIdx]), row, 2);
                                        logDataTable.setValueAt(ffb, row, 3);
                                        logDataTable.setValueAt(afr, row, 4);
                                        logDataTable.setValueAt(Double.valueOf(flds[logMafColIdx]), row, 5);
                                        logDataTable.setValueAt(Double.valueOf(flds[logSdColIdx]), row, 6);
                                        row += 1;
                                    } else
                                        removed = true;
                                } else
                                    removed = true;
                            } catch (NumberFormatException e) {
                                logger.error(e);
                                JOptionPane.showMessageDialog(null,
                                        "Error parsing number at " + file.getName() + " line " + i + ": " + e,
                                        "Error processing file", JOptionPane.ERROR_MESSAGE);
                                return;
                            }
                            i += 1;
                        }
                    } finally {
                        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                    }
                }
            } catch (Exception e) {
                logger.error(e);
                JOptionPane.showMessageDialog(null, e, "Error opening file", JOptionPane.ERROR_MESSAGE);
            } finally {
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        logger.error(e);
                    }
                }
            }
        }
    }

    protected boolean processLog() {
        try {
            double mapG = 1;
            double mapO = 0;
            String mpStr = mpType.getSelectedItem().toString();
            String sdStr = sdType.getSelectedItem().toString();
            if (mpStr.contains("Torr"))
                mapG = 1.0 / 51.715;
            if (mpStr.contains("Abs") && sdStr.contains("RR"))
                mapO = -14.7;
            else if (mpStr.contains("Rel") && sdStr.contains("Cobb"))
                mapO = 14.7;

            String rpmStr, iatStr, afrStr, mafStr, ffbStr;
            LogData logData;
            xData = new HashMap<Double, HashMap<Double, ArrayList<LogData>>>();
            HashMap<Double, ArrayList<LogData>> yData;
            ArrayList<LogData> data;
            for (int i = 0; i < logDataTable.getRowCount(); ++i) {
                rpmStr = logDataTable.getValueAt(i, 0).toString();
                iatStr = logDataTable.getValueAt(i, 1).toString();
                mpStr = logDataTable.getValueAt(i, 2).toString();
                ffbStr = logDataTable.getValueAt(i, 3).toString();
                afrStr = logDataTable.getValueAt(i, 4).toString();
                mafStr = logDataTable.getValueAt(i, 5).toString();
                sdStr = logDataTable.getValueAt(i, 6).toString();
                if (rpmStr.isEmpty() || mpStr.isEmpty() || iatStr.isEmpty() || afrStr.isEmpty() || mafStr.isEmpty()
                        || ffbStr.isEmpty() || sdStr.isEmpty())
                    continue;
                logData = new LogData();
                logData.mp = (Double.valueOf(mpStr) * mapG) + mapO;

                if (logData.mp < mpMin)
                    continue;

                logData.rpm = Double.valueOf(rpmStr);
                logData.mp = xAxisArray.get(Utils.closestValueIndex(logData.mp, xAxisArray));
                logData.rpm = yAxisArray.get(Utils.closestValueIndex(logData.rpm, yAxisArray));
                logData.iat = Double.valueOf(iatStr);
                logData.maf = Double.valueOf(mafStr);
                logData.sd = Double.valueOf(sdStr);
                logData.afr = Double.valueOf(afrStr);
                logData.ffb = Double.valueOf(ffbStr);
                logData.sderr = ((logData.sd - logData.maf) / logData.maf) * 100.0;
                if (isOl)
                    logData.afrerr = ((logData.afr - logData.ffb) / logData.ffb) * 100.0;
                else
                    logData.afrerr = trims.get(i);// + ((14.7 - logData.ffb) / 14.7 * 100);

                yData = xData.get(logData.mp);
                if (yData == null) {
                    yData = new HashMap<Double, ArrayList<LogData>>();
                    xData.put(logData.mp, yData);
                }
                data = yData.get(logData.rpm);
                if (data == null) {
                    data = new ArrayList<LogData>();
                    yData.put(logData.rpm, data);
                }
                data.add(logData);
            }
            return true;
        } catch (Exception e) {
            logger.error(e);
            JOptionPane.showMessageDialog(null, e, "Error processing data", JOptionPane.ERROR_MESSAGE);
        }
        return false;
    }

    protected boolean displayData() {
        try {
            int cnt;
            double x, y, val;
            boolean isMaf = (dataType.getSelectedIndex() == 0 ? true : false);
            ArrayList<LogData> data;
            HashMap<Double, ArrayList<LogData>> yData;
            Color[][] colorMatrix = new Color[corrTable.getRowCount()][corrTable.getColumnCount()];
            for (int i = 1; i < xAxisArray.size() + 1; ++i) {
                newTable.setValueAt(origTable.getValueAt(0, i), 0, i);
                corrTable.setValueAt(origTable.getValueAt(0, i), 0, i);
                corrCountTable.setValueAt(origTable.getValueAt(0, i), 0, i);
                for (int j = 1; j < yAxisArray.size() + 1; ++j) {
                    if (i == 1) {
                        newTable.setValueAt(origTable.getValueAt(j, 0), j, 0);
                        corrTable.setValueAt(origTable.getValueAt(j, 0), j, 0);
                        corrCountTable.setValueAt(origTable.getValueAt(j, 0), j, 0);
                    }
                    x = xAxisArray.get(i - 1);
                    y = yAxisArray.get(j - 1);
                    yData = xData.get(x);
                    if (yData == null)
                        newTable.setValueAt(origTable.getValueAt(j, i), j, i);
                    else {
                        data = yData.get(y);
                        if (data == null)
                            newTable.setValueAt(origTable.getValueAt(j, i), j, i);
                        else {
                            cnt = data.size();
                            val = 0;
                            for (LogData d : data)
                                val += (isMaf ? d.sderr : d.afrerr);
                            val /= cnt;
                            corrTable.setValueAt(val, j, i);
                            corrCountTable.setValueAt(cnt, j, i);
                            if (cnt > minCellHitCount) {
                                val = 1 + (val / 100.0 * corrApplied) / 100.0;
                                if (isMaf)
                                    newTable.setValueAt(Double.valueOf(origTable.getValueAt(j, i).toString()) / val,
                                            j, i);
                                else
                                    newTable.setValueAt(Double.valueOf(origTable.getValueAt(j, i).toString()) * val,
                                            j, i);
                                colorMatrix[j][i] = Color.PINK;
                            } else
                                newTable.setValueAt(origTable.getValueAt(j, i), j, i);
                        }
                    }
                }
            }
            Utils.colorTable(newTable);

            for (int i = 0; i < colorMatrix.length; ++i)
                colorMatrix[i][0] = Color.LIGHT_GRAY;
            for (int i = 0; i < colorMatrix[0].length; ++i)
                colorMatrix[0][i] = Color.LIGHT_GRAY;
            ((BgColorFormatRenderer) corrTable.getDefaultRenderer(Object.class)).setColors(colorMatrix);
            ((BgColorFormatRenderer) corrCountTable.getDefaultRenderer(Object.class)).setColors(colorMatrix);

            plotCorrectionData();

            return true;
        } catch (Exception e) {
            logger.error(e);
            JOptionPane.showMessageDialog(null, e, "Error processing data", JOptionPane.ERROR_MESSAGE);
        }
        return false;
    }

    private boolean plotCorrectionData() {
        plot3d.removeAllPlots();
        XYSeries series;
        XYPlot plot = chartPanel.getChart().getXYPlot();
        XYSeriesCollection lineDataset = (XYSeriesCollection) plot.getDataset(0);
        DecimalFormat df = new DecimalFormat(".00");
        String val;
        int i = 0;
        int j = 0;
        if (!Utils.isTableEmpty(corrTable)) {
            try {
                for (i = 1; i < corrTable.getColumnCount(); ++i) {
                    val = corrTable.getValueAt(0, i).toString();
                    series = new XYSeries(df.format(Double.valueOf(val)));
                    for (j = 1; j < corrTable.getRowCount(); ++j) {
                        if (corrTable.getValueAt(j, i) != null) {
                            val = corrTable.getValueAt(j, i).toString();
                            if (!val.isEmpty())
                                series.add(Double.valueOf(corrTable.getValueAt(j, 0).toString()),
                                        Double.valueOf(val));
                        }
                    }
                    if (series.getItemCount() > 0) {
                        corrData.add(series);
                        series.setDescription(series.getKey().toString());
                        lineDataset.addSeries(series);
                    }
                }
                plot.getDomainAxis(0).setAutoRange(true);
                plot.getRangeAxis(0).setAutoRange(true);
                plot.getDomainAxis(0).setLabel(xAxisName);
                plot.getRangeAxis(0).setLabel(yAxisName);
                plot.getRenderer(0).setSeriesVisible(0, false);

                double[] x = new double[xAxisArray.size()];
                for (i = 0; i < xAxisArray.size(); ++i)
                    x[i] = xAxisArray.get(i);
                double[] y = new double[yAxisArray.size()];
                for (i = 0; i < yAxisArray.size(); ++i)
                    y[i] = yAxisArray.get(i);
                double[][] z = Utils.doubleZArray(corrTable, x, y);
                Color[][] colors = Utils.generateTableColorMatrix(corrTable, 1, 1);
                plot3d.addGridPlot("Average Error % Plot", colors, x, y, z);
            } catch (NumberFormatException e) {
                logger.error(e);
                JOptionPane.showMessageDialog(null,
                        "Error parsing number from " + corrTableName + " table, cell(" + i + " : " + j + "): " + e,
                        "Error", JOptionPane.ERROR_MESSAGE);
                return false;
            }
        }
        return true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        checkActionPerformed(e);
    }
}