package com.vgi.mafscaling;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.awt.event.ActionListener;
import java.io.File;
import java.net.URI;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.UIDefaults;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
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.XYDotRenderer;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
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 abstract class AMafScaling extends FCTabbedPane implements IMafChartHolder, ActionListener {
private static final long serialVersionUID = -1494227355521802829L;
protected static final int ColumnWidth = 55;
protected static final String MafTableName = "Current MAF Scaling";
protected static final String currentDataName = "Current";
protected static final String correctedDataName = "Corrected";
protected static final String smoothedDataName = "Smoothed";
protected static final String mafCurveDataName = "Smoothed Maf Curve";
protected static final String currentSlopeDataName = "Current Maf Slope";
protected static final String smoothedSlopeDataName = "Smoothed Maf Slope";
protected static final String XAxisName = "MAF Sensor (Voltage)";
protected static final String Y1AxisName = "Mass Airflow (g/s)";
protected final ExcelAdapter excelAdapter = new ExcelAdapter();
protected PrimaryOpenLoopFuelingTable polfTable = null;
protected MafCompare mafCompare = null;
protected MafChartPanel mafChartPanel = null;
protected JTable mafTable = null;
protected JTable mafSmoothingTable = null;
protected JCheckBox checkBoxSmoothing = null;
protected JComboBox<String> smoothComboBox = null;
protected JCheckBox checkBoxCurrentMaf = null;
protected JCheckBox checkBoxCorrectedMaf = null;
protected JCheckBox checkBoxSmoothedMaf = null;
protected JCheckBox checkBoxRunData = null;
protected JButton btnCompareButton = null;
protected JButton btnSmoothButton = null;
protected JButton btnPlusButton = null;
protected JButton btnMinusButton = null;
protected JLabel lblMafIncDec = null;
protected JFormattedTextField mafIncDecTextField = null;
protected ArrayList<Double> rpmArray = new ArrayList<Double>();
protected ArrayList<Double> mafvArray = new ArrayList<Double>();
protected ArrayList<Double> voltArray = new ArrayList<Double>();
protected ArrayList<Double> gsArray = new ArrayList<Double>();
protected ArrayList<Double> gsCorrected = new ArrayList<Double>();
protected ArrayList<Double> smoothGsArray = new ArrayList<Double>();
protected XYSeries currMafData = new XYSeries(currentDataName);
protected XYSeries corrMafData = new XYSeries(correctedDataName);
protected XYSeries smoothMafData = new XYSeries(smoothedDataName);
protected XYSeries runData = null;
protected Insets insets0 = new Insets(0, 0, 0, 0);
protected Insets insets1 = new Insets(1, 1, 1, 1);
protected Insets insets2 = new Insets(2, 2, 2, 2);
protected Insets insets3 = new Insets(3, 3, 3, 3);
protected String[] optionButtons = { "Yes", "No", "No to all" };
public AMafScaling(int tabPlacement, PrimaryOpenLoopFuelingTable table, MafCompare comparer) {
super(tabPlacement);
polfTable = table;
mafCompare = comparer;
}
protected void initialize() {
createDataTab();
createGraphTab();
createUsageTab();
}
public abstract void loadData();
public abstract void saveData();
protected abstract void createRunPanel(JPanel dataPanel);
protected abstract void createGraphTab();
protected abstract void onEnableSmoothingView(boolean flag);
protected abstract void onSmoothReset();
protected abstract void calculateMafScaling();
protected abstract void clearRunTables();
protected abstract void loadLogFile();
protected abstract String usage();
protected void selectLogFile() {
fileChooser.setMultiSelectionEnabled(true);
if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this))
return;
loadLogFile();
}
protected void onDroppedFiles(List<File> files) {
if (files.size() > 0 && getSelectedIndex() == 0) {
fileChooser.setMultiSelectionEnabled(true);
fileChooser.setCurrentDirectory(files.get(0));
fileChooser.setSelectedFiles((File[])files.toArray());
fileChooser.approveSelection();
loadLogFile();
}
}
protected void createDataTab() {
JPanel dataPanel = new JPanel();
add(dataPanel, "<html><div style='text-align: center;'>D<br>a<br>t<br>a</div></html>");
GridBagLayout gbl_dataPanel = new GridBagLayout();
gbl_dataPanel.columnWidths = new int[] {0};
gbl_dataPanel.rowHeights = new int[] {0, 0, 0, 0};
gbl_dataPanel.columnWeights = new double[]{1.0};
gbl_dataPanel.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0};
dataPanel.setLayout(gbl_dataPanel);
createControlPanel(dataPanel);
createMafPanel(dataPanel);
createRunControlPanel(dataPanel);
createRunPanel(dataPanel);
}
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;
dataPanel.add(cntlPanel, gbl_ctrlPanel);
GridBagLayout gbl_cntlPanel = new GridBagLayout();
gbl_cntlPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0};
gbl_cntlPanel.rowHeights = new int[]{0, 0};
gbl_cntlPanel.columnWeights = new double[]{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, "Clear Maf Data", "clearmaf", GridBagConstraints.WEST);
addButton(cntlPanel, 1, "Clear Run Data", "clearrun", GridBagConstraints.WEST);
addButton(cntlPanel, 2, "Clear All", "clearall", GridBagConstraints.WEST);
addButton(cntlPanel, 3, "Load", "load", GridBagConstraints.WEST);
addButton(cntlPanel, 4, "Save", "save", GridBagConstraints.WEST);
addButton(cntlPanel, 5, "GO", "go", GridBagConstraints.EAST);
}
protected void createMafPanel(JPanel dataPanel) {
MafTablePane mafScrollPane = new MafTablePane(ColumnWidth, MafTableName, true, true);
mafTable = mafScrollPane.getJTable();
excelAdapter.addTable(mafTable, false, false, false, false, false, false, false, false, true);
GridBagConstraints gbc_mafScrollPane = new GridBagConstraints();
gbc_mafScrollPane.ipady = 30;
gbc_mafScrollPane.anchor = GridBagConstraints.PAGE_START;
gbc_mafScrollPane.insets = insets0;
gbc_mafScrollPane.fill = GridBagConstraints.HORIZONTAL;
gbc_mafScrollPane.gridx = 0;
gbc_mafScrollPane.gridy = 1;
dataPanel.add(mafScrollPane, gbc_mafScrollPane);
}
protected void createRunControlPanel(JPanel dataPanel) {
JPanel dataRunButtonPanel = new JPanel();
dataRunButtonPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
GridBagConstraints gbc_dataRunButtonPanel = new GridBagConstraints();
gbc_dataRunButtonPanel.anchor = GridBagConstraints.PAGE_START;
gbc_dataRunButtonPanel.weightx = 1.0;
gbc_dataRunButtonPanel.insets = insets0;
gbc_dataRunButtonPanel.fill = GridBagConstraints.HORIZONTAL;
gbc_dataRunButtonPanel.gridx = 0;
gbc_dataRunButtonPanel.gridy = 2;
dataPanel.add(dataRunButtonPanel, gbc_dataRunButtonPanel);
GridBagLayout gbl_dataRunButtonPanel = new GridBagLayout();
gbl_dataRunButtonPanel.columnWidths = new int[]{0, 0};
gbl_dataRunButtonPanel.rowHeights = new int[]{0, 0};
gbl_dataRunButtonPanel.columnWeights = new double[]{0.0, 1.0};
gbl_dataRunButtonPanel.rowWeights = new double[]{0};
dataRunButtonPanel.setLayout(gbl_dataRunButtonPanel);
addButton(dataRunButtonPanel, 0, "POL Fueling", "fueling", GridBagConstraints.WEST);
addButton(dataRunButtonPanel, 1, "Load Log", "loadlog", GridBagConstraints.WEST);
}
protected JPanel createGraphPlotPanel(JPanel cntlPanel) {
JPanel plotPanel = new JPanel();
GridBagLayout gbl_plotPanel = new GridBagLayout();
gbl_plotPanel.columnWidths = new int[] {0};
gbl_plotPanel.rowHeights = new int[] {0, 0, 0};
gbl_plotPanel.columnWeights = new double[]{1.0};
gbl_plotPanel.rowWeights = new double[]{0.0, 1.0, 0.0};
plotPanel.setLayout(gbl_plotPanel);
GridBagConstraints gbl_ctrlPanel = new GridBagConstraints();
gbl_ctrlPanel.insets = insets3;
gbl_ctrlPanel.anchor = GridBagConstraints.NORTH;
gbl_ctrlPanel.fill = GridBagConstraints.HORIZONTAL;
gbl_ctrlPanel.weightx = 1.0;
gbl_ctrlPanel.gridx = 0;
gbl_ctrlPanel.gridy = 0;
plotPanel.add(cntlPanel, gbl_ctrlPanel);
return plotPanel;
}
protected void createChart(JPanel plotPanel, String y2AxisName) {
JFreeChart chart = ChartFactory.createScatterPlot(null, null, null, null, PlotOrientation.VERTICAL, false, true, false);
chart.setBorderVisible(true);
mafChartPanel = new MafChartPanel(chart, this);
GridBagConstraints gbl_chartPanel = new GridBagConstraints();
gbl_chartPanel.anchor = GridBagConstraints.CENTER;
gbl_chartPanel.fill = GridBagConstraints.BOTH;
gbl_chartPanel.insets = insets3;
gbl_chartPanel.weightx = 1.0;
gbl_chartPanel.weighty = 1.0;
gbl_chartPanel.gridx = 0;
gbl_chartPanel.gridy = 1;
plotPanel.add(mafChartPanel.getChartPanel(), gbl_chartPanel);
XYDotRenderer dotRenderer = new XYDotRenderer();
dotRenderer.setSeriesPaint(0, new Color(0, 51, 102));
dotRenderer.setDotHeight(3);
dotRenderer.setDotWidth(3);
XYSplineRenderer lineRenderer = new XYSplineRenderer(3);
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.setSeriesStroke(1, stroke);
lineRenderer.setSeriesStroke(2, stroke);
lineRenderer.setSeriesPaint(0, new Color(34, 139, 34));
lineRenderer.setSeriesPaint(1, new Color(0, 0, 255));
lineRenderer.setSeriesPaint(2, new Color(201, 0, 0));
lineRenderer.setSeriesShape(0, ShapeUtilities.createDiamond((float) 2.5));
lineRenderer.setSeriesShape(1, ShapeUtilities.createUpTriangle((float) 2.5));
lineRenderer.setSeriesShape(2, ShapeUtilities.createDownTriangle((float) 2.5));
mafChartPanel.enablePointsDrag(0);
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();
}
}
);
ValueAxis mafvDomain = new NumberAxis(XAxisName);
ValueAxis mafgsRange = new NumberAxis(Y1AxisName);
ValueAxis afrerrRange = new NumberAxis(y2AxisName);
XYSeriesCollection scatterDataset = new XYSeriesCollection(runData);
XYSeriesCollection lineDataset = new XYSeriesCollection();
currMafData.setDescription(currentDataName);
corrMafData.setDescription(correctedDataName);
smoothMafData.setDescription(smoothedDataName);
lineDataset.addSeries(smoothMafData);
lineDataset.addSeries(corrMafData);
lineDataset.addSeries(currMafData);
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, mafvDomain);
plot.setRangeAxis(0, mafgsRange);
plot.mapDatasetToDomainAxis(0, 0);
plot.mapDatasetToRangeAxis(0, 0);
plot.setDataset(1, scatterDataset);
plot.setRenderer(1, dotRenderer);
plot.setRangeAxis(1, afrerrRange);
plot.mapDatasetToDomainAxis(1, 0);
plot.mapDatasetToRangeAxis(1, 1);
LegendTitle legend = new LegendTitle(plot.getRenderer());
legend.setItemFont(new Font("Arial", 0, 10));
legend.setPosition(RectangleEdge.TOP);
chart.addLegend(legend);
}
protected void createGraphCommonControls(JPanel cntlPanel, int column) {
checkBoxCurrentMaf = addCheckBox(cntlPanel, column, "Current", "current");
checkBoxCorrectedMaf = addCheckBox(cntlPanel, ++column, "Corrected", "corrected");
checkBoxSmoothedMaf = addCheckBox(cntlPanel, ++column, "Smoothed", "smoothed");
btnCompareButton = addButton(cntlPanel, ++column, "Compare", "compare", GridBagConstraints.CENTER);
checkBoxSmoothing = addCheckBox(cntlPanel, ++column, "Smoothing:", "smoothing");
smoothComboBox = addComboBox(cntlPanel, ++column, new String[]{ " 3 ", " 5 ", " 7 " });
btnSmoothButton = addButton(cntlPanel, ++column, "Apply", "smooth", GridBagConstraints.WEST);
addButton(cntlPanel, ++column, "Reset", "smoothreset", GridBagConstraints.WEST);
}
protected void createMafSmoothingPanel(JPanel plotPanel) {
Dimension minDimension = new Dimension(26, 26);
NumberFormat doubleFmt = NumberFormat.getNumberInstance();
doubleFmt.setMaximumFractionDigits(2);
JPanel mafSmoothingPanel = new JPanel();
GridBagLayout gbl_mafSmoothingPanel = new GridBagLayout();
gbl_mafSmoothingPanel.columnWidths = new int[]{0, 0, 0};
gbl_mafSmoothingPanel.rowHeights = new int[] {0, 0};
gbl_mafSmoothingPanel.columnWeights = new double[]{0.0, 0.0, 1.0};
gbl_mafSmoothingPanel.rowWeights = new double[]{0.0, 0.0};
GridBagConstraints gbc_mafSmoothingPanel = new GridBagConstraints();
gbc_mafSmoothingPanel.ipady = 3;
gbc_mafSmoothingPanel.anchor = GridBagConstraints.SOUTH;
gbc_mafSmoothingPanel.weightx = 1.0;
gbc_mafSmoothingPanel.insets = new Insets(0, 0, 5, 0);
gbc_mafSmoothingPanel.fill = GridBagConstraints.HORIZONTAL;
gbc_mafSmoothingPanel.gridx = 0;
gbc_mafSmoothingPanel.gridy = 2;
mafSmoothingPanel.setLayout(gbl_mafSmoothingPanel);
plotPanel.add(mafSmoothingPanel, gbc_mafSmoothingPanel);
GridBagConstraints gbc_ctrl = new GridBagConstraints();
gbc_ctrl.anchor = GridBagConstraints.CENTER;
gbc_ctrl.insets = insets1;
gbc_ctrl.gridx = 0;
gbc_ctrl.gridy = 0;
lblMafIncDec = new JLabel("Inc/Dec");
mafSmoothingPanel.add(lblMafIncDec, gbc_ctrl);
mafIncDecTextField = new JFormattedTextField(doubleFmt);
mafIncDecTextField.setValue(new Double(0.1));
mafIncDecTextField.setColumns(5);
mafIncDecTextField.setMinimumSize(minDimension);
gbc_ctrl.fill = GridBagConstraints.HORIZONTAL;
gbc_ctrl.gridy++;
mafSmoothingPanel.add(mafIncDecTextField, gbc_ctrl);
UIDefaults nimbusInsets = new UIDefaults();
nimbusInsets.put("Button.contentMargins", insets3);
btnPlusButton = new JButton("<html><div style='text-align: center; font-weight: bold;'>+</div></html>");
btnPlusButton.setActionCommand("plus");
btnPlusButton.addActionListener(this);
btnPlusButton.setMinimumSize(minDimension);
btnPlusButton.setMargin(insets3);
btnPlusButton.putClientProperty("Nimbus.Overrides", nimbusInsets);
gbc_ctrl.gridx++;
gbc_ctrl.gridy--;
mafSmoothingPanel.add(btnPlusButton, gbc_ctrl);
btnMinusButton = new JButton("<html><div style='text-align: center; font-weight: bold;'>-</div></html>");
btnMinusButton.setActionCommand("minus");
btnMinusButton.addActionListener(this);
btnMinusButton.setMinimumSize(minDimension);
btnMinusButton.setMargin(insets3);
btnMinusButton.putClientProperty("Nimbus.Overrides", nimbusInsets);
gbc_ctrl.gridy++;
mafSmoothingPanel.add(btnMinusButton, gbc_ctrl);
MafTablePane mafSmoothingPane = new MafTablePane(ColumnWidth, null, false, false);
mafSmoothingPane.hideRowHeaders();
mafSmoothingTable = mafSmoothingPane.getJTable();
excelAdapter.addTable(mafSmoothingTable, false, true, true, false, false, true, false, false, true);
GridBagConstraints gbc_mafSmoothingPane = new GridBagConstraints();
gbc_mafSmoothingPane.anchor = GridBagConstraints.SOUTH;
gbc_mafSmoothingPane.fill = GridBagConstraints.HORIZONTAL;
gbc_mafSmoothingPane.insets = insets0;
gbc_mafSmoothingPane.gridx = 2;
gbc_mafSmoothingPane.gridy = 0;
gbc_mafSmoothingPane.gridheight = 2;
gbc_mafSmoothingPane.weightx = 1.0;
gbc_mafSmoothingPane.ipady = 30;
mafSmoothingPanel.add(mafSmoothingPane, gbc_mafSmoothingPane);
lblMafIncDec.setVisible(false);
mafIncDecTextField.setVisible(false);
btnPlusButton.setVisible(false);
btnMinusButton.setVisible(false);
}
protected JButton addButton(JPanel panel, int column, String name, String action, int align) {
JButton button = new JButton(name);
button.setActionCommand(action);
button.addActionListener(this);
GridBagConstraints gbc_button = new GridBagConstraints();
gbc_button.anchor = align;
gbc_button.insets = insets2;
gbc_button.gridx = column;
gbc_button.gridy = 0;
if (GridBagConstraints.CENTER == align)
gbc_button.weightx = 1.0;
panel.add(button, gbc_button);
return button;
}
protected JCheckBox addCheckBox(JPanel panel, int column, String name, String action) {
JCheckBox check = new JCheckBox(name);
check.setActionCommand(action);
check.addActionListener(this);
GridBagConstraints gbc_check = new GridBagConstraints();
gbc_check.insets = new Insets(3, 3, 3, 0);
gbc_check.gridx = column;
gbc_check.gridy = 0;
panel.add(check, gbc_check);
return check;
}
protected JComboBox<String> addComboBox(JPanel panel, int column, String[] values) {
JComboBox<String> combo = new JComboBox<String>(values);
combo.setSelectedIndex(0);
combo.setEnabled(false);
GridBagConstraints gbc_combo = new GridBagConstraints();
gbc_combo.anchor = GridBagConstraints.WEST;
gbc_combo.insets = insets2;
gbc_combo.gridx = column;
gbc_combo.gridy = 0;
panel.add(combo, gbc_combo);
return combo;
}
protected boolean getMafTableData(ArrayList<Double> voltArray, ArrayList<Double> gsArray) {
String value;
for (int i = 0; i < mafTable.getColumnCount(); ++i) {
for (int j = 0; j < mafTable.getRowCount(); ++j) {
value = mafTable.getValueAt(j, i).toString();
if (value.isEmpty() && i > 0)
return true;
if (!Utils.validateDouble(value, j, i, MafTableName))
return false;
}
voltArray.add(Double.parseDouble(mafTable.getValueAt(0, i).toString()));
gsArray.add(Double.parseDouble(mafTable.getValueAt(1, i).toString()));
}
if (voltArray.size() != gsArray.size()) {
JOptionPane.showMessageDialog(null, "Data sets (volt/gs) in " + MafTableName + " have different length", "Invalid Data", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
protected void clearMafTable() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
while (MafTablePane.MafTableColumnCount < mafTable.getColumnCount())
Utils.removeColumn(MafTablePane.MafTableColumnCount, mafTable);
Utils.clearTable(mafTable);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
protected void clearData() {
mafvArray.clear();
rpmArray.clear();
voltArray.clear();
gsArray.clear();
gsCorrected.clear();
smoothGsArray.clear();
}
protected void clearNotRunDataCheckboxes() {
if (checkBoxRunData.isSelected()) {
checkBoxRunData.setSelected(false);
runData.clear();
}
if (checkBoxCurrentMaf.isSelected()) {
checkBoxCurrentMaf.setSelected(false);
currMafData.clear();
}
if (checkBoxCorrectedMaf.isSelected()) {
checkBoxCorrectedMaf.setSelected(false);
corrMafData.clear();
}
if (checkBoxSmoothedMaf.isSelected()) {
checkBoxSmoothedMaf.setSelected(false);
smoothMafData.clear();
}
}
protected void clearChartCheckBoxes() {
checkBoxRunData.setSelected(false);
checkBoxCurrentMaf.setSelected(false);
checkBoxCorrectedMaf.setSelected(false);
checkBoxSmoothedMaf.setSelected(false);
}
protected void enableSmoothingView(boolean flag) {
if (smoothGsArray.size() == 0) {
checkBoxSmoothing.setSelected(false);
return;
}
smoothComboBox.setEnabled(flag);
btnSmoothButton.setEnabled(flag);
checkBoxRunData.setEnabled(!flag);
checkBoxCurrentMaf.setEnabled(!flag);
checkBoxCorrectedMaf.setEnabled(!flag);
checkBoxSmoothedMaf.setEnabled(!flag);
clearChartData();
onEnableSmoothingView(flag);
if (flag == true) {
lblMafIncDec.setVisible(true);
mafIncDecTextField.setVisible(true);
btnPlusButton.setVisible(true);
btnMinusButton.setVisible(true);
setCorrectedMafData();
plotSmoothingLineSlopes();
corrMafData.setDescription(mafCurveDataName);
currMafData.setDescription(currentSlopeDataName);
smoothMafData.setDescription(smoothedSlopeDataName);
}
else {
lblMafIncDec.setVisible(false);
mafIncDecTextField.setVisible(false);
btnPlusButton.setVisible(false);
btnMinusButton.setVisible(false);
currMafData.setDescription(currentDataName);
corrMafData.setDescription(correctedDataName);
smoothMafData.setDescription(smoothedDataName);
}
}
protected void clearChartData() {
runData.clear();
currMafData.clear();
corrMafData.clear();
smoothMafData.clear();
}
protected void smoothReset() {
if (gsCorrected.size() == 0)
return;
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
smoothGsArray.clear();
smoothGsArray.addAll(gsCorrected);
setXYTable(mafSmoothingTable, voltArray, smoothGsArray);
corrMafData.clear();
onSmoothReset();
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
protected void changeMafSmoothingCellValue(boolean add) {
if (!Pattern.matches(Utils.fpRegex, mafIncDecTextField.getText())) {
JOptionPane.showMessageDialog(null, "Invalid Maf Scaling increment/decrement value", "Invalid value", JOptionPane.ERROR_MESSAGE);
return;
}
double smoothingIncrement = Double.valueOf(mafIncDecTextField.getText());
int[] rows = mafSmoothingTable.getSelectedRows();
int[] cols = mafSmoothingTable.getSelectedColumns();
if (rows == null || cols == null) {
JOptionPane.showMessageDialog(null, "Please select MAF table cell(s) to apply increment/decrement.", "Invalid selection", JOptionPane.ERROR_MESSAGE);
return;
}
double val;
for (int col : cols) {
if (!Pattern.matches(Utils.fpRegex, mafSmoothingTable.getValueAt(1, col).toString()))
continue;
val = (Double)(mafSmoothingTable.getValueAt(1, col)) + (add == true ? smoothingIncrement : smoothingIncrement * -1.0);
mafSmoothingTable.setValueAt(val, 1, col);
smoothGsArray.set(col, val);
corrMafData.updateByIndex(col, val);
if (col == 0)
smoothMafData.updateByIndex(col, (smoothGsArray.get(col + 1) - smoothGsArray.get(col)) / (voltArray.get(col + 1) - voltArray.get(col)));
else if (col == smoothGsArray.size() - 1)
smoothMafData.updateByIndex(col - 1, (smoothGsArray.get(col) - smoothGsArray.get(col - 1)) / (voltArray.get(col) - voltArray.get(col - 1)));
else {
smoothMafData.updateByIndex(col, (smoothGsArray.get(col + 1) - smoothGsArray.get(col)) / (voltArray.get(col + 1) - voltArray.get(col)));
smoothMafData.updateByIndex(col - 1, (smoothGsArray.get(col) - smoothGsArray.get(col - 1)) / (voltArray.get(col) - voltArray.get(col - 1)));
}
}
}
public void onMovePoint(int itemIndex, double valueX, double valueY) {
ArrayList<Double> xarr = voltArray;
ArrayList<Double> yarr = smoothGsArray;
XYSeries series = smoothMafData;
if (checkBoxSmoothing.isSelected() == false)
yarr.set(itemIndex, valueY);
else {
double X1 = xarr.get(itemIndex);
double Y1 = yarr.get(itemIndex);
double X2 = xarr.get(itemIndex + 1);
double Y2 = X2 * valueY - X1 * valueY + Y1;
yarr.set(itemIndex + 1, Y2);
mafSmoothingTable.setValueAt(Y2, 1, itemIndex + 1);
mafSmoothingTable.changeSelection(1, itemIndex + 1, false, false);
corrMafData.updateByIndex(itemIndex + 1, Y2);
if (itemIndex + 1 < series.getItemCount()) {
X1 = X2;
X2 = xarr.get(itemIndex + 2);
Y1 = Y2;
Y2 = yarr.get(itemIndex + 2);
valueY = (Y2 - Y1) / (X2 - X1);
series.updateByIndex(itemIndex + 1, valueY);
}
}
}
protected void createUsageTab() {
final Desktop desktop = Desktop.getDesktop();
JTextPane usageTextArea = new JTextPane();
usageTextArea.setMargin(new Insets(10, 10, 10, 10));
usageTextArea.setContentType("text/html");
usageTextArea.setText(usage());
usageTextArea.setEditable(false);
usageTextArea.setCaretPosition(0);
usageTextArea.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
try {
desktop.browse(new URI(e.getURL().toString()));
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
});
JScrollPane textScrollPane = new JScrollPane(usageTextArea);
textScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
textScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
add(textScrollPane, "<html><div style='text-align: center;'>U<br>s<br>a<br>g<br>e</div></html>");
}
protected boolean setCorrectedMafData() {
return setXYSeries(corrMafData, voltArray, gsCorrected);
}
protected boolean setSmoothedMafData() {
return setXYSeries(smoothMafData, voltArray, smoothGsArray);
}
protected boolean setXYSeries(XYSeries series, ArrayList<Double> xarr, ArrayList<Double> yarr) {
if (xarr.size() == 0 || xarr.size() != yarr.size())
return false;
series.clear();
for (int i = 0; i < xarr.size(); ++i)
series.add(xarr.get(i), yarr.get(i), false);
series.fireSeriesChanged();
return true;
}
protected void smoothCurve() {
if (!checkBoxSmoothing.isSelected() || voltArray.size() == 0 || smoothGsArray.size() == 0)
return;
int degree = Integer.parseInt(smoothComboBox.getSelectedItem().toString().trim());
int[] rows = mafSmoothingTable.getSelectedRows();
int[] cols = mafSmoothingTable.getSelectedColumns();
if (rows == null || cols == null || cols.length < degree) {
JOptionPane.showMessageDialog(null, "Please select MAF Scaling table cells range to apply smoothing. Number of selected columns must be greater than the smoothing degree value.", "Invalid selection", JOptionPane.ERROR_MESSAGE);
return;
}
setCursor(new Cursor(Cursor.WAIT_CURSOR));
int start = cols[0];
int end = cols[cols.length - 1];
try {
int movWind;
int i;
ArrayList<Double> tmpArray = new ArrayList<Double>();
if (degree == 3) {
movWind = 1;
for (i = movWind + start; i + movWind <= end; ++i)
tmpArray.add(0.25 * smoothGsArray.get(i - 1) +
0.5 * smoothGsArray.get(i) +
0.25 * smoothGsArray.get(i + 1));
for (i = 0; i < tmpArray.size(); ++i)
smoothGsArray.set(i + movWind + start, tmpArray.get(i));
}
if (degree == 5) {
movWind = 2;
for (i = movWind + start; i + movWind <= end; ++i)
tmpArray.add(0.1 * smoothGsArray.get(i - 2) +
0.2 * smoothGsArray.get(i - 1) +
0.4 * smoothGsArray.get(i) +
0.2 * smoothGsArray.get(i + 1) +
0.1 * smoothGsArray.get(i + 2));
for (i = 0; i < tmpArray.size(); ++i)
smoothGsArray.set(i + movWind + start, tmpArray.get(i));
}
if (degree == 7) {
movWind = 3;
for (i = movWind + start; i + movWind <= end; ++i)
tmpArray.add(0.05 * smoothGsArray.get(i - 3) +
0.1 * smoothGsArray.get(i - 2) +
0.15 * smoothGsArray.get(i - 1) +
0.4 * smoothGsArray.get(i) +
0.15 * smoothGsArray.get(i + 1) +
0.1 * smoothGsArray.get(i + 2) +
0.05 * smoothGsArray.get(i + 3));
for (i = 0; i < tmpArray.size(); ++i)
smoothGsArray.set(i + movWind + start, tmpArray.get(i));
}
plotSmoothingLineSlopes();
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
protected boolean plotCurrentMafData() {
ArrayList<Double> xarr = voltArray;
ArrayList<Double> yarr = gsArray;
if (xarr.size() == 0 || yarr.size() == 0 || xarr.size() != yarr.size()) {
xarr = new ArrayList<Double>();
yarr = new ArrayList<Double>();
if (mafTable.getValueAt(0, 0).toString().trim().isEmpty())
return false;
if (!getMafTableData(xarr, yarr))
return false;
}
return setXYSeries(currMafData, xarr, yarr);
}
protected void plotSmoothingLineSlopes() {
currMafData.clear();
smoothMafData.clear();
plotLineSlope(currMafData, voltArray, gsArray);
plotLineSlope(smoothMafData, voltArray, smoothGsArray);
setXYTable(mafSmoothingTable, voltArray, smoothGsArray);
}
private void plotLineSlope(XYSeries series, ArrayList<Double> xarr, ArrayList<Double> yarr) {
if (xarr.size() == 0 || yarr.size() == 0 || xarr.size() != yarr.size())
return;
for (int j = 0; j < xarr.size() - 1; ++j)
series.add((double)xarr.get(j + 1), (double)((yarr.get(j + 1) - yarr.get(j)) / (xarr.get(j + 1) - xarr.get(j))));
}
protected boolean setXYTable(JTable table, ArrayList<Double> xarr, ArrayList<Double> yarr) {
if (xarr.size() == 0 || yarr.size() == 0 || xarr.size() != yarr.size())
return false;
for (int i = 0; i < xarr.size(); ++i) {
Utils.ensureColumnCount(i + 1, table);
table.setValueAt(xarr.get(i), 0, i);
table.setValueAt(smoothGsArray.get(i), 1, i);
}
return true;
}
protected boolean checkActionPerformed(ActionEvent e) {
if ("clearmaf".equals(e.getActionCommand())) {
clearMafTable();
}
else if ("clearrun".equals(e.getActionCommand())) {
clearRunTables();
}
else if ("clearall".equals(e.getActionCommand())) {
clearMafTable();
clearRunTables();
}
else if ("load".equals(e.getActionCommand())) {
loadData();
}
else if ("save".equals(e.getActionCommand())) {
saveData();
}
else if ("go".equals(e.getActionCommand())) {
calculateMafScaling();
}
else if ("compare".equals(e.getActionCommand())) {
mafCompare.setReferenceMafTables(mafTable, mafSmoothingTable);
mafCompare.setVisible(true);
}
else if ("smooth".equals(e.getActionCommand())) {
smoothCurve();
}
else if ("smoothreset".equals(e.getActionCommand())) {
smoothReset();
}
else if ("plus".equals(e.getActionCommand())) {
changeMafSmoothingCellValue(true);
}
else if ("minus".equals(e.getActionCommand())) {
changeMafSmoothingCellValue(false);
}
else if ("fueling".equals(e.getActionCommand())) {
polfTable.getSetUserFueling();
}
else if ("loadlog".equals(e.getActionCommand())) {
selectLogFile();
}
else
return false;
return true;
}
}