/* * 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.Color; import java.awt.Cursor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.Format; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; 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.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextPane; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.UIDefaults; import javax.swing.border.LineBorder; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import org.apache.log4j.Logger; import org.math.plot.Plot3DPanel; import org.math.plot.plots.HistogramPlot3D; public class LogStats extends FCTabbedPane implements ActionListener { private enum Statistics {COUNT, MINIMUM, MAXIMUM, MEAN, MEDIAN, MODE, RANGE, VARIANCE, STDDEV}; private enum Plot3D {GRID, HIST, BAR, LINE, SCATTER}; private enum DataFilter {NONE, LESS, LESS_EQUAL, EQUAL, GREATER_EQUAL, GREATER}; private static final long serialVersionUID = -7486851151646396168L; private static final Logger logger = Logger.getLogger(LogStats.class); private static final int ColumnWidth = 50; private static final int DataTableRowCount = 50; private static final int DataTableColumnCount = 25; private static final String timeMatchString = "^\\s*time\\s*(\\(.*\\))?$"; private static final String SetFilters = "<html><center>Set<br>Filters</center></html>"; private static final String ViewFilters = "<html><center>View<br>Filters</center></html>"; public class JFmtTextField extends JFormattedTextField { private static final long serialVersionUID = -8767848259312656943L; public JFmtTextField(NumberFormat format) { super(format); } @Override protected void processFocusEvent(final FocusEvent e) { if (e.isTemporary()) { return; } if (e.getID() == FocusEvent.FOCUS_LOST) { if (getText() == null || getText().isEmpty()) { setValue(null); } } super.processFocusEvent(e); } }; private File[] logFiles = null; private ArrayList<File> logFilesTodo = null; private JComboBox<String> xAxisColumn = null; private JComboBox<String> yAxisColumn = null; private JMultiSelectionBox dataColumn = null; private JComboBox<String> statistics = null; private JFormattedTextField xAxisRoundTextBox = null; private JFormattedTextField yAxisRoundTextBox = null; private ArrayList<JButton> filterButtonList = null; private ArrayList<JComboBox<String>> filterComboBoxList = null; private ArrayList<JComboBox<String>> filterColumnList = null; private ArrayList<JFormattedTextField> filterTextBoxList = null; private JTable dataTable = null; private JPanel cntlPanel = null; private JLabel labelFileName = null; private JButton btnSetFiltersButton = null; private ExcelAdapter excelAdapter = null; private HashMap<Double, HashMap<Double, ArrayList<Double>>> xData = null; private Plot3DPanel plot = null; private ButtonGroup rbGroup = new ButtonGroup(); private ArrayList<Double> xAxisArray; private ArrayList<Double> yAxisArray; private int distance = 50; private Insets insets0 = new Insets(0, 0, 0, 0); private Insets insets3 = new Insets(3, 3, 3, 3); private UIDefaults buttonInsets6 = new UIDefaults(); private UIDefaults buttonInsets10 = new UIDefaults(); public LogStats(int tabPlacement) { super(tabPlacement); initialize(); } private void initialize() { excelAdapter = new ExcelAdapter(); xAxisArray = new ArrayList<Double>(); yAxisArray = new ArrayList<Double>(); filterButtonList = new ArrayList<JButton>(); filterComboBoxList = new ArrayList<JComboBox<String>>(); filterColumnList = new ArrayList<JComboBox<String>>(); filterTextBoxList = new ArrayList<JFormattedTextField>(); createDataTab(); createGraghTab(); createUsageTab(); } ////////////////////////////////////////////////////////////////////////////////////// // DATA TAB ////////////////////////////////////////////////////////////////////////////////////// private 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}; gbl_dataPanel.columnWeights = new double[]{0.0}; gbl_dataPanel.rowWeights = new double[]{0.0, 1.0}; dataPanel.setLayout(gbl_dataPanel); createControlPanel(dataPanel); createDataPanel(dataPanel); } private void createControlPanel(JPanel dataPanel) { try { NumberFormat doubleFmt = NumberFormat.getNumberInstance(); doubleFmt.setGroupingUsed(false); doubleFmt.setMaximumFractionDigits(2); doubleFmt.setMinimumFractionDigits(1); doubleFmt.setRoundingMode(RoundingMode.HALF_UP); NumberFormat doubleFmtFilters = NumberFormat.getNumberInstance(); doubleFmtFilters.setGroupingUsed(false); doubleFmtFilters.setMaximumFractionDigits(6); doubleFmtFilters.setMinimumFractionDigits(0); doubleFmtFilters.setRoundingMode(RoundingMode.HALF_UP); buttonInsets6.put("Button.contentMargins", new Insets(6, 6, 6, 6)); buttonInsets10.put("Button.contentMargins", new Insets(6, 10, 6, 10)); cntlPanel = new JPanel(); GridBagConstraints gbc_ctrlPanel = new GridBagConstraints(); gbc_ctrlPanel.insets = insets3; gbc_ctrlPanel.anchor = GridBagConstraints.PAGE_START; gbc_ctrlPanel.fill = GridBagConstraints.HORIZONTAL; gbc_ctrlPanel.weightx = 1.0; gbc_ctrlPanel.gridx = 0; gbc_ctrlPanel.gridy = 0; dataPanel.add(cntlPanel, gbc_ctrlPanel); GridBagLayout gbl_cntlPanel = new GridBagLayout(); gbl_cntlPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; gbl_cntlPanel.rowHeights = new int[]{0, 0, 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.2, 0.0, 1.0}; gbl_cntlPanel.rowWeights = new double[]{0.0, 0.0, 0.0}; cntlPanel.setLayout(gbl_cntlPanel); JButton selectLogButton = addButton(0, 0, 2, "<html><center>Select<br>Log</center></html>", "selectlog"); selectLogButton.setMargin(new Insets(3, 5, 3, 5)); selectLogButton.putClientProperty("Nimbus.Overrides", buttonInsets6); addLabel(0, 1, "X-Axis"); xAxisColumn = addComboBox(0, 2, null); addLabel(1, 1, "Y-Axis"); yAxisColumn = addComboBox(1, 2, null); addLabel(0, 3, "Data"); dataColumn = new JMultiSelectionBox(); GridBagConstraints gbc_dataColumn = new GridBagConstraints(); gbc_dataColumn.anchor = GridBagConstraints.WEST; gbc_dataColumn.insets = new Insets(3, 0, 3, 3); gbc_dataColumn.gridx = 4; gbc_dataColumn.gridy = 0; dataColumn.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXX"); cntlPanel.add(dataColumn, gbc_dataColumn); addLabel(1, 3, "Stats"); statistics = addComboBox(1, 4, new String[] {"Count", "Minimum", "Maximum", "Mean", "Median", "Mode", "Range", "Variance", "Standard Deviation"}); addLabel(0, 5, "X-Step"); xAxisRoundTextBox = addTextField(0, 6, 5, doubleFmt, true); addLabel(1, 5, "Y-Step"); yAxisRoundTextBox = addTextField(1, 6, 5, doubleFmt, true); addLabel(0, 7, "or"); JButton btnSetAxisButton = addButton(0, 8, 2, "<html><center>Set<br>Axis</center></html>", "setaxis"); btnSetAxisButton.setMargin(new Insets(3, 9, 3, 9)); btnSetAxisButton.putClientProperty("Nimbus.Overrides", buttonInsets10); btnSetFiltersButton = addButton(0, 9, 2, SetFilters, "setfilters"); btnSetFiltersButton.setMargin(new Insets(3, 5, 3, 5)); btnSetFiltersButton.putClientProperty("Nimbus.Overrides", buttonInsets6); JButton clearFiltersButton = addButton(0, 10, 2, "<html><center>Clear<br>Filters</center></html>", "clearfilters"); clearFiltersButton.setMargin(new Insets(3, 5, 3, 5)); clearFiltersButton.putClientProperty("Nimbus.Overrides", buttonInsets6); addButton(0, 11, 2, "GO", "go"); labelFileName = new JLabel(""); labelFileName.setHorizontalAlignment(SwingConstants.CENTER); GridBagConstraints gbc_label = new GridBagConstraints(); gbc_label.anchor = GridBagConstraints.WEST; gbc_label.fill = GridBagConstraints.HORIZONTAL; gbc_label.insets = insets3; gbc_label.gridx = 0; gbc_label.gridy = 2; gbc_label.gridwidth = gbl_cntlPanel.columnWidths.length; cntlPanel.add(labelFileName, gbc_label); } catch (Exception e) { logger.error(e); e.printStackTrace(); } } private void createDataPanel(JPanel dataPanel) { TableColumnModel dataTableModel = new DefaultTableColumnModel(); dataTableModel.addColumn(new TableColumn(0, 250)); dataTable = new JTable() { private static final long serialVersionUID = 6526901361175099297L; public boolean isCellEditable(int row, int column) { return false; }; }; dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); dataTable.setColumnSelectionAllowed(true); dataTable.setCellSelectionEnabled(true); dataTable.setBorder(new LineBorder(new Color(0, 0, 0))); dataTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); dataTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); dataTable.setModel(new DefaultTableModel(DataTableRowCount, DataTableColumnCount)); dataTable.setTableHeader(null); Utils.initializeTable(dataTable, ColumnWidth); Format[][] formatMatrix = { { new DecimalFormat("0.00"), new DecimalFormat("0.00") } }; NumberFormatRenderer renderer = (NumberFormatRenderer)dataTable.getDefaultRenderer(Object.class); renderer.setFormats(formatMatrix); GridBagConstraints gbc_dataTable = new GridBagConstraints(); gbc_dataTable.insets = insets3; gbc_dataTable.anchor = GridBagConstraints.PAGE_START; gbc_dataTable.fill = GridBagConstraints.BOTH; gbc_dataTable.weightx = 1.0; gbc_dataTable.weighty = 1.0; gbc_dataTable.gridx = 0; gbc_dataTable.gridy = 1; gbc_dataTable.gridwidth = 14; JScrollPane scrollPane = new JScrollPane(dataTable); dataPanel.add(scrollPane, gbc_dataTable); excelAdapter.addTable(dataTable, false, true, true, true, true, true, true, true, true); } private JButton addButton(int row, int column, int rowspan, String name, String action) { JButton button = new JButton(name); button.setActionCommand(action); button.addActionListener(this); GridBagConstraints gbc_button = new GridBagConstraints(); gbc_button.anchor = GridBagConstraints.EAST; gbc_button.insets = insets3; gbc_button.gridx = column; gbc_button.gridy = row; gbc_button.gridheight = rowspan; cntlPanel.add(button, gbc_button); return button; } private void addLabel(int row, int column, String text) { JLabel label = new JLabel(text); GridBagConstraints gbc_label = new GridBagConstraints(); gbc_label.anchor = GridBagConstraints.EAST; gbc_label.insets = insets3; gbc_label.gridx = column; gbc_label.gridy = row; if (text.equals("or")) { gbc_label.gridheight = 2; gbc_label.insets = insets0; } cntlPanel.add(label, gbc_label); } private JComboBox<String> addComboBox(int row, int column, String[] values) { JComboBox<String> combo; if (values != null) combo = new JComboBox<String>(values); else { combo = new JComboBox<String>(); combo.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXX"); } GridBagConstraints gbc_combo = new GridBagConstraints(); gbc_combo.anchor = GridBagConstraints.WEST; gbc_combo.insets = new Insets(3, 0, 3, 3); gbc_combo.gridx = column; gbc_combo.gridy = row; cntlPanel.add(combo, gbc_combo); return combo; } private JFormattedTextField addTextField(int row, int column, int numColumns, NumberFormat format, boolean fill) { JFormattedTextField textField = new JFormattedTextField(format); textField.setColumns(numColumns); textField.setMinimumSize(textField.getPreferredSize()); textField.setMaximumSize(textField.getPreferredSize()); GridBagConstraints gbc_textField = new GridBagConstraints(); gbc_textField.anchor = GridBagConstraints.WEST; if (fill) gbc_textField.fill = GridBagConstraints.HORIZONTAL; gbc_textField.insets = new Insets(3, 0, 3, 3); //gbc_textField.weightx = 1; gbc_textField.gridx = column; gbc_textField.gridy = row; cntlPanel.add(textField, gbc_textField); return textField; } ////////////////////////////////////////////////////////////////////////////////////// // CREATE CHART TAB ////////////////////////////////////////////////////////////////////////////////////// private void createGraghTab() { JPanel plotPanel = new JPanel(); add(plotPanel, "<html><div style='text-align: center;'>3<br>D<br> <br>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 = insets3; 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, 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, 1.0}; gbl_cntlPanel.rowWeights = new double[]{0}; cntlPanel.setLayout(gbl_cntlPanel); addRadioButton(cntlPanel, 0, "Grid", "grid"); addRadioButton(cntlPanel, 1, "Histogram", "hist"); addRadioButton(cntlPanel, 2, "Bar", "bar"); addRadioButton(cntlPanel, 3, "Line", "line"); addRadioButton(cntlPanel, 4, "Scatter", "scatter"); plot = new Plot3DPanel("SOUTH") { private static final long serialVersionUID = 7914951068593204419L; public void addPlotToolBar(String location) { super.addPlotToolBar(location); super.plotToolBar.remove(7); super.plotToolBar.remove(5); super.plotToolBar.remove(4); } }; plot.setAutoBounds(); plot.setAutoscrolls(true); plot.setEditable(false); plot.setBorder(BorderFactory.createLineBorder(Color.BLACK)); plot.setForeground(Color.BLACK); plot.getAxis(0).setColor(Color.BLACK); plot.getAxis(1).setColor(Color.BLACK); plot.getAxis(2).setColor(Color.BLACK); GridBagConstraints gbl_chartPanel = new GridBagConstraints(); gbl_chartPanel.anchor = GridBagConstraints.CENTER; gbl_chartPanel.insets = insets3; 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(plot, gbl_chartPanel); } protected void addRadioButton(JPanel panel, int column, String name, String action) { JRadioButton button = new JRadioButton(name); button.setActionCommand(action); button.addActionListener(this); rbGroup.add(button); GridBagConstraints gbc_button = new GridBagConstraints(); gbc_button.anchor = GridBagConstraints.WEST; gbc_button.insets = new Insets(0, 0, 3, 3); gbc_button.gridx = column; gbc_button.gridy = 0; panel.add(button, gbc_button); } ////////////////////////////////////////////////////////////////////////////////////// // CREATE USAGE TAB ////////////////////////////////////////////////////////////////////////////////////// private void createUsageTab() { 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); 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>"); } private String usage() { ResourceBundle bundle; bundle = ResourceBundle.getBundle("com.vgi.mafscaling.logstats"); return bundle.getString("usage"); } ////////////////////////////////////////////////////////////////////////////////////// // WORK FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////// private void setAxis() { ArrayList<Integer> distancePct = new ArrayList<Integer>(); distancePct.add(distance); new LogStatsFixedAxis(distancePct, xAxisArray, yAxisArray); if (xAxisArray.size() > 0) xAxisRoundTextBox.setValue(null); if (yAxisArray.size() > 0) yAxisRoundTextBox.setValue(null); distance = distancePct.get(0); } private void setFilters() { String[] colNames = new String[xAxisColumn.getItemCount()]; for (int i = 0; i < xAxisColumn.getItemCount(); ++i) colNames[i] = xAxisColumn.getItemAt(i); new LogStatsFilters(colNames, filterButtonList, filterColumnList, filterComboBoxList, filterTextBoxList); if (filterButtonList.size() > 0) btnSetFiltersButton.setText(ViewFilters); else btnSetFiltersButton.setText(SetFilters); } private void clearFilters() { filterButtonList.clear(); filterColumnList.clear(); filterComboBoxList.clear(); filterTextBoxList.clear(); btnSetFiltersButton.setText(SetFilters); } private void selectLogColumns() { fileChooser.setMultiSelectionEnabled(true); if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this)) return; getLogColumns(); } private void getLogColumns() { Object xAxis = xAxisColumn.getSelectedItem(); Object yAxis = yAxisColumn.getSelectedItem(); List<String> data = dataColumn.getSelectedItems(); xAxisColumn.removeAllItems(); yAxisColumn.removeAllItems(); dataColumn.removeAllItems(); dataColumn.setText(""); labelFileName.setText(""); Object[] filterArr = new Object[filterButtonList.size()]; for (int k = 0; k < filterButtonList.size(); ++k) { filterArr[k] = filterColumnList.get(k).getSelectedItem(); filterColumnList.get(k).removeAllItems(); filterColumnList.get(k).addItem(""); } logFiles = fileChooser.getSelectedFiles(); logFilesTodo = new ArrayList<File>(); BufferedReader br = null; HashSet<String> columns = new HashSet<String>(); String logTimeColName = Config.getLogTimeColumnName(); for (File logFile : logFiles) { try { br = new BufferedReader(new InputStreamReader(new FileInputStream(logFile.getAbsoluteFile()), Config.getEncoding())); String line = null; String [] elements = null; while ((line = br.readLine()) != null && (elements = line.split(Utils.fileFieldSplitter, -1)) != null && elements.length < 2) continue; if (logFilesTodo.size() == 0) { logFilesTodo.add(logFile); Arrays.sort(elements); for (String item : elements) { if (logFiles.length > 1 && (item.equals(logTimeColName) || item.toLowerCase().matches(timeMatchString))) continue; xAxisColumn.addItem(item); yAxisColumn.addItem(item); dataColumn.addItem(item); for (int k = 0; k < filterButtonList.size(); ++k) filterColumnList.get(k).addItem(item); } } else { columns.clear(); for (String item : elements) columns.add(item); boolean skipFile = false; for (int i = 1; i < xAxisColumn.getItemCount(); ++i) { if (!columns.contains(xAxisColumn.getItemAt(i))) { skipFile = true; JOptionPane.showMessageDialog(null, "File " + logFile.getName() + " does not have column '" + xAxisColumn.getItemAt(i) + "'\nSkipping file...", "Missing column", JOptionPane.WARNING_MESSAGE); break; } } if (skipFile) continue; logFilesTodo.add(logFile); } } 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); } } } } if (xAxis != null) xAxisColumn.setSelectedItem(xAxis); if (yAxis != null) yAxisColumn.setSelectedItem(yAxis); if (data != null) dataColumn.setSelectedItems(data); for (int k = filterButtonList.size() - 1; k >= 0 ; --k) { if (filterArr[k] != null) { filterColumnList.get(k).setSelectedItem(filterArr[k]); if (filterColumnList.get(k).getSelectedIndex() == -1 || filterColumnList.get(k).getSelectedItem().equals("")) { filterButtonList.remove(k); filterComboBoxList.remove(k); filterColumnList.remove(k); filterTextBoxList.remove(k); } } } if (filterButtonList.size() > 0) { filterButtonList.set(0, null); btnSetFiltersButton.setText(ViewFilters); } else btnSetFiltersButton.setText(SetFilters); StringBuffer sb = new StringBuffer(""); for (File logFile : logFilesTodo) sb.append(logFile.getName()).append(", "); if (sb.length() >= 2) sb.delete(sb.length() - 2, sb.length()); labelFileName.setText("[" + sb.toString() + "]"); } private Statistics getStatId() { if (statistics.getSelectedItem() == null) return Statistics.MEAN; String name = (String)statistics.getSelectedItem(); if ("Count".equals(name)) return Statistics.COUNT; if ("Minimum".equals(name)) return Statistics.MINIMUM; if ("Maximum".equals(name)) return Statistics.MAXIMUM; if ("Mean".equals(name)) return Statistics.MEAN; if ("Median".equals(name)) return Statistics.MEDIAN; if ("Mode".equals(name)) return Statistics.MODE; if ("Range".equals(name)) return Statistics.RANGE; if ("Variance".equals(name)) return Statistics.VARIANCE; if ("Std Devn".equals(name)) return Statistics.STDDEV; return Statistics.MEAN; } private DataFilter getType(JComboBox<String> filter) { if (filter.getSelectedItem() == null) return DataFilter.NONE; String name = (String)filter.getSelectedItem(); if ("<".equals(name)) return DataFilter.LESS; if ("<=".equals(name)) return DataFilter.LESS_EQUAL; if ("=".equals(name)) return DataFilter.EQUAL; if (">=".equals(name)) return DataFilter.GREATER_EQUAL; if (">".equals(name)) return DataFilter.GREATER; return DataFilter.NONE; } private int getFilterRounding(JFormattedTextField filterTextBox) { int rounding = 0; String filterString = filterTextBox.getText(); if (filterString.indexOf('.') != -1) { filterString = filterString.substring(filterString.indexOf('.')); rounding = filterString.length() - 1; } return rounding; } private boolean checkAgainstFilter(double value, DataFilter type, double filter, int rounding) { boolean ret = true; switch (type) { case LESS: if (value >= filter) ret = false; break; case LESS_EQUAL: if (value > filter) ret = false; break; case EQUAL: double rndVal = value; if (rounding > 0) { double multiplier = Math.pow(10.0, rounding); rndVal = Math.round(value * multiplier) / multiplier; } else rndVal = Math.round(value); if (!Utils.equals(rndVal, filter)) ret = false; break; case GREATER_EQUAL: if (value < filter) ret = false; break; case GREATER: if (value <= filter) ret = false; break; default: break; } return ret; } private void processLog() { // Get and validate required fields Utils.clearTable(dataTable); int xAxisArraySize = xAxisArray.size(); int yAxisArraySize = yAxisArray.size(); if (xAxisColumn.getSelectedItem() == null || yAxisColumn.getSelectedItem() == null || dataColumn.getSelectedItems() == null) { JOptionPane.showMessageDialog(null, "lease select X-Axis, Y-Axis, and Data columns.", "Error", JOptionPane.ERROR_MESSAGE); return; } if (xAxisRoundTextBox.getValue() == null && xAxisArraySize == 0) { JOptionPane.showMessageDialog(null, "X-Axis scaling is not set. Please set 'Step' or X-Axis values.", "Error", JOptionPane.ERROR_MESSAGE); return; } if (yAxisRoundTextBox.getValue() == null && yAxisArraySize == 0) { JOptionPane.showMessageDialog(null, "Y-Axis scaling is not set. Please set 'Step' or Y-Axis values.", "Error", JOptionPane.ERROR_MESSAGE); return; } double xRound = Double.NaN; if (xAxisRoundTextBox.getValue() != null) { xRound = (((Number)xAxisRoundTextBox.getValue()).doubleValue()); if (xRound < 0.01) { JOptionPane.showMessageDialog(null, "Incorrect X-Axis scaling, minimum allowed is 0.01", "Error", JOptionPane.ERROR_MESSAGE); return; } } double yRound = Double.NaN; if (yAxisRoundTextBox.getValue() != null) { yRound = (((Number)yAxisRoundTextBox.getValue()).doubleValue()); if (yRound < 0.01) { JOptionPane.showMessageDialog(null, "Incorrect Y-Axis scaling, minimum allowed is 0.01", "Error", JOptionPane.ERROR_MESSAGE); return; } } setCursor(new Cursor(Cursor.WAIT_CURSOR)); Statistics statid = getStatId(); String xAxisColName = (String)xAxisColumn.getSelectedItem(); String yAxisColName = (String)yAxisColumn.getSelectedItem(); List<String> dataColNames = dataColumn.getSelectedItems(); // Get filters DataFilter[] filterTypeArr = new DataFilter[filterButtonList.size()]; String[] filterColNameArr = new String[filterButtonList.size()]; double[] filterArr = new double[filterButtonList.size()]; int[] filterRoundingArr = new int[filterButtonList.size()]; boolean[] useFilterArr = new boolean[filterButtonList.size()]; boolean[] isFilterAndArr = new boolean[filterButtonList.size()]; for (int k = 0; k < filterButtonList.size(); ++k) { filterTypeArr[k] = getType(filterComboBoxList.get(k)); if (filterColumnList.get(k).getSelectedItem() != null) filterColNameArr[k] = (String)filterColumnList.get(k).getSelectedItem(); filterArr[k] = (filterTextBoxList.get(k).getValue() != null ? (((Number)filterTextBoxList.get(k).getValue()).doubleValue()) : Double.NaN); filterRoundingArr[k] = getFilterRounding(filterTextBoxList.get(k)); if (!filterColNameArr[k].isEmpty() && filterTypeArr[k] != DataFilter.NONE && !Double.isNaN(filterArr[k])) { useFilterArr[k] = true; isFilterAndArr[k] = (k > 0 && "or".equals(filterButtonList.get(k).getText()) ? false : true); } } TreeSet<Double> xVals = new TreeSet<Double>(); TreeSet<Double> yVals = new TreeSet<Double>(); // data struct where first hash set is X-Axis containing second hash set which is Y-Axis containing array of values xData = new HashMap<Double, HashMap<Double, ArrayList<Double>>>(); // Process log files for (File logFile : logFilesTodo) { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(new FileInputStream(logFile.getAbsoluteFile()), Config.getEncoding())); String line = null; String [] elements = null; while ((line = br.readLine()) != null && (elements = line.split(Utils.fileFieldSplitter, -1)) != null && elements.length < 2) continue; ArrayList<String> columns = new ArrayList<String>(Arrays.asList(elements)); int xColIdx = columns.indexOf(xAxisColName); int yColIdx = columns.indexOf(yAxisColName); ArrayList<Integer> vColIdxArray = new ArrayList<Integer>(); for (String dataColName : dataColNames) vColIdxArray.add(columns.indexOf(dataColName)); int[] fltrColIdxArr = new int[filterButtonList.size()]; double fltrVal; for (int k = 0; k < filterButtonList.size(); ++k) fltrColIdxArr[k] = (useFilterArr[k] ? columns.indexOf(filterColNameArr[k]) : -1); double x, y, val, dst, totdst; double distratio = distance / 100.0; int idx = 0; int lastXIdx = xAxisArraySize - 1; int lastYIdx = yAxisArraySize - 1; int i = 2; boolean skip; int tmColIdx = -1; HashMap<Double, ArrayList<Double>> yData; ArrayList<Double> data; try { line = br.readLine(); while (line != null) { elements = line.split(Utils.fileFieldSplitter, -1); if (i == 2) { boolean found = false; for (int k = 0; !found && k < filterButtonList.size(); ++k) { if (useFilterArr[k] && elements[fltrColIdxArr[k]].matches(Utils.tmRegex)) tmColIdx = fltrColIdxArr[k]; found = true; } if (!found) { if (elements[xColIdx].matches(Utils.tmRegex)) tmColIdx = xColIdx; else if (elements[yColIdx].matches(Utils.tmRegex)) tmColIdx = yColIdx; } if (tmColIdx >= 0) Utils.resetBaseTime(elements[tmColIdx]); } if (tmColIdx >= 0) elements[tmColIdx] = String.valueOf(Utils.parseTime(elements[tmColIdx])); // Check if value passes all filters boolean passFilters = true; for (int k = 0; k < filterButtonList.size() && useFilterArr[k]; ++k) { if (!Pattern.matches(Utils.fpRegex, elements[fltrColIdxArr[k]])) { JOptionPane.showMessageDialog(null, "Invalid value for Filter " + k + ", file " + logFile.getName() + ", column " + (fltrColIdxArr[k] + 1) + ", row " + i, "Invalid value", JOptionPane.ERROR_MESSAGE); return; } fltrVal = Utils.parseValue(elements[fltrColIdxArr[k]]); if (isFilterAndArr[k]) passFilters = (passFilters && checkAgainstFilter(fltrVal, filterTypeArr[k], filterArr[k], filterRoundingArr[k])); else passFilters = (passFilters || checkAgainstFilter(fltrVal, filterTypeArr[k], filterArr[k], filterRoundingArr[k])); } // Value should be processed if (passFilters) { if (!Pattern.matches(Utils.fpRegex, elements[xColIdx]) && !Pattern.matches(Utils.onOffRegex, elements[xColIdx])) { JOptionPane.showMessageDialog(null, "Invalid value for X-Axis, file " + logFile.getName() + ", column " + (xColIdx + 1) + ", row " + i, "Invalid value", JOptionPane.ERROR_MESSAGE); return; } if (!Pattern.matches(Utils.fpRegex, elements[yColIdx]) && !Pattern.matches(Utils.onOffRegex, elements[yColIdx])) { JOptionPane.showMessageDialog(null, "Invalid value for Y-Axis, file " + logFile.getName() + ", column " + (yColIdx + 1) + ", row " + i, "Invalid value", JOptionPane.ERROR_MESSAGE); return; } skip = false; if (Double.isNaN(xRound)) { val = Utils.parseValue(elements[xColIdx]); idx = Utils.closestValueIndex(val, xAxisArray); x = xAxisArray.get(idx); if (distance < 50 && xAxisArraySize > 1) { if (val < x) { dst = x - val; if (idx == 0) totdst = xAxisArray.get(idx + 1) - x; else totdst = x - xAxisArray.get(idx - 1); } else { dst = val - x; if (idx == lastXIdx) totdst = x - xAxisArray.get(idx - 1); else totdst = xAxisArray.get(idx + 1) - x; } if (distratio < dst / totdst) skip = true; } } else { x = Utils.round(Utils.parseValue(elements[xColIdx]), xRound); xVals.add(x); } if (Double.isNaN(yRound)) { val = Utils.parseValue(elements[yColIdx]); idx = Utils.closestValueIndex(val, yAxisArray); y = yAxisArray.get(idx); if (distance < 50 && yAxisArraySize > 1) { if (val < y) { dst = y - val; if (idx == 0) totdst = yAxisArray.get(idx + 1) - y; else totdst = y - yAxisArray.get(idx - 1); } else { dst = val - y; if (idx == lastYIdx) totdst = y - yAxisArray.get(idx - 1); else totdst = yAxisArray.get(idx + 1) - y; } if (distratio < dst / totdst) skip = true; } } else { y = Utils.round(Utils.parseValue(elements[yColIdx]), yRound); yVals.add(y); } val = 0; for (Integer vColIdx : vColIdxArray) { if (!Pattern.matches(Utils.fpRegex, elements[vColIdx]) && !Pattern.matches(Utils.onOffRegex, elements[vColIdx])) { JOptionPane.showMessageDialog(null, "Invalid value for Data, file " + logFile.getName() + ", column " + (vColIdx + 1) + ", row " + i, "Invalid value", JOptionPane.ERROR_MESSAGE); return; } val += Utils.parseValue(elements[vColIdx]); } yData = xData.get(x); if (yData == null) { yData = new HashMap<Double, ArrayList<Double>>(); xData.put(x, yData); } data = yData.get(y); if (data == null) { data = new ArrayList<Double>(); yData.put(y, data); } if (!skip) data.add(val); } line = br.readLine(); i += 1; } } catch (Exception e) { logger.error(e); JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE); } } 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); } } } } setCursor(new Cursor(Cursor.WAIT_CURSOR)); if (xVals.size() > 0) { xAxisArray.clear(); xAxisArray.addAll(xVals); } if (yVals.size() > 0) { yAxisArray.clear(); yAxisArray.addAll(yVals); } processData(statid); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } public void processData(Statistics id) { try { Utils.ensureColumnCount(xAxisArray.size() + 1, dataTable); Utils.ensureRowCount(yAxisArray.size() + 1, dataTable); int x = 0; int y = 0; double val = 0; HashMap<Double, ArrayList<Double>> xentry; ArrayList<Double> yentry; for (double xval : xAxisArray) { dataTable.setValueAt(xval, 0, ++x); xentry = xData.get(xval); if (xentry == null) continue; y = 0; for (double yval : yAxisArray) { dataTable.setValueAt(yval, ++y, 0); yentry = xentry.get(yval); if (yentry == null || yentry.size() == 0) continue; switch (id) { case COUNT: val = yentry.size(); break; case MINIMUM: val = Collections.min(yentry); break; case MAXIMUM: val = Collections.max(yentry); break; case MEAN: val = Utils.mean(yentry); break; case MEDIAN: val = Utils.median(yentry); break; case MODE: val = Utils.mode(yentry); break; case RANGE: val = Utils.range(yentry); break; case VARIANCE: val = Utils.variance(yentry); break; case STDDEV: val = Utils.standardDeviation(yentry); break; } dataTable.setValueAt(Double.isNaN(val) ? "" : val, y, x); } } if (xData.size() > 0) { int i; // remove extra rows for (i = dataTable.getRowCount() - 1; i >= 0 && dataTable.getValueAt(i, 0).toString().equals(""); --i) Utils.removeRow(i, dataTable); // remove extra columns for (i = dataTable.getColumnCount() - 1; i >= 0 && dataTable.getValueAt(0, i).toString().equals(""); --i) Utils.removeColumn(i, dataTable); Utils.colorTable(dataTable); } else { Utils.clearTable(dataTable); } JRadioButton button = (JRadioButton) rbGroup.getElements().nextElement(); button.setSelected(true); display3D(Plot3D.GRID); } catch (Exception e) { logger.error(e); JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE); } } private void addGridPlot() { if (xData == null || xData.size() == 0) return; TreeMap<Double, Integer> xAxisMap = new TreeMap<Double, Integer>(); TreeMap<Double, Integer> yAxisMap = new TreeMap<Double, Integer>(); for (Map.Entry<Double, HashMap<Double, ArrayList<Double>>> xentry : xData.entrySet()) { xAxisMap.put(xentry.getKey(), 0); for (Map.Entry<Double, ArrayList<Double>> yentry : xentry.getValue().entrySet()) yAxisMap.put(yentry.getKey(), 0); } double[] x = new double[xAxisMap.size()]; int i = 0; for (Double key : xAxisMap.keySet()) x[i++] = key; double[] y = new double[yAxisMap.size()]; i = 0; for (Double key : yAxisMap.keySet()) y[i++] = key; double[][] z = Utils.doubleZArray(dataTable, x, y); Color[][] colors = Utils.doubleColorArray(dataTable, x, y); plot.addGridPlot(dataColumn.getSelectedItemsString() + " " + statistics.getSelectedItem().toString(), colors, x, y, z); } private void addHistogramPlot(Color[] colors, double[][] xyzArray) { double minXDiff = Double.NaN; double minYDiff = Double.NaN; double diff; for (int i = 1; i < dataTable.getColumnCount() - 1; ++i) { diff = Double.valueOf(dataTable.getValueAt(0, i + 1).toString()) - Double.valueOf(dataTable.getValueAt(0, i).toString()); if (diff < minXDiff || Double.isNaN(minXDiff)) minXDiff = diff; } for (int i = 1; i < dataTable.getRowCount() - 1; ++i) { diff = Double.valueOf(dataTable.getValueAt(i + 1, 0).toString()) - Double.valueOf(dataTable.getValueAt(i, 0).toString()); if (diff < minYDiff || Double.isNaN(minYDiff)) minYDiff = diff; } plot.addPlot(new HistogramPlot3D(dataColumn.getSelectedItemsString() + " " + statistics.getSelectedItem().toString(), colors, xyzArray, minXDiff, minYDiff)); } private void addBarLineScatterPlot(Plot3D type) { if (xData == null || xData.size() == 0) return; int k = 0; String val; double X, Y; double[][] array = new double[dataTable.getColumnCount() * dataTable.getRowCount()][3]; BgColorFormatRenderer renderer = (BgColorFormatRenderer)dataTable.getDefaultRenderer(Object.class); ArrayList<Color> colors = new ArrayList<Color>(); for (int i = 1; i < dataTable.getColumnCount(); ++i) { val = dataTable.getValueAt(0, i).toString(); if (val.isEmpty()) break; X = Double.valueOf(val.toString()); for (int j = 1; j < dataTable.getRowCount(); ++j) { val = dataTable.getValueAt(j, 0).toString(); if (val.isEmpty()) break; Y = Double.valueOf(val.toString()); val = dataTable.getValueAt(j, i).toString(); if (!val.isEmpty()) { colors.add(renderer.getColorAt(j, i)); array[k][0] = X; array[k][1] = Y; array[k++][2] = Double.valueOf(val); } } } double[][] xyzArray = new double[k][3]; for (k = 0; k < xyzArray.length; ++k) System.arraycopy(array[k], 0, xyzArray[k], 0, 3); switch (type) { case BAR: plot.addBarPlot(dataColumn.getSelectedItemsString() + " " + statistics.getSelectedItem().toString(), colors.toArray(new Color[colors.size()]), xyzArray); break; case HIST: addHistogramPlot(colors.toArray(new Color[colors.size()]), xyzArray); break; case LINE: plot.addLinePlot(dataColumn.getSelectedItemsString() + " " + statistics.getSelectedItem().toString(), colors.toArray(new Color[colors.size()]), xyzArray); break; case SCATTER: plot.addScatterPlot(dataColumn.getSelectedItemsString() + " " + statistics.getSelectedItem().toString(), colors.toArray(new Color[colors.size()]), xyzArray); default: break; } } private void display3D(Plot3D type) { plot.removeAllPlots(); switch (type) { case GRID: addGridPlot(); break; case HIST: addBarLineScatterPlot(type); break; case BAR: addBarLineScatterPlot(type); break; case LINE: addBarLineScatterPlot(type); break; case SCATTER: addBarLineScatterPlot(type); break; default: return; } plot.setAxisLabel(0, xAxisColumn.getSelectedItem().toString()); plot.setAxisLabel(1, yAxisColumn.getSelectedItem().toString()); plot.setAxisLabel(2, dataColumn.getSelectedItemsString()); } @Override public void actionPerformed(ActionEvent e) { if ("selectlog".equals(e.getActionCommand())) selectLogColumns(); else if ("go".equals(e.getActionCommand())) processLog(); else if ("setaxis".equals(e.getActionCommand())) setAxis(); else if ("setfilters".equals(e.getActionCommand())) setFilters(); else if ("clearfilters".equals(e.getActionCommand())) clearFilters(); else if ("grid".equals(e.getActionCommand())) { if (xData != null) display3D(Plot3D.GRID); } else if ("hist".equals(e.getActionCommand())) { if (xData != null) display3D(Plot3D.HIST); } else if ("bar".equals(e.getActionCommand())) { if (xData != null) display3D(Plot3D.BAR); } else if ("line".equals(e.getActionCommand())) { if (xData != null) display3D(Plot3D.LINE); } else if ("scatter".equals(e.getActionCommand())) { if (xData != null) display3D(Plot3D.SCATTER); } } 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(); getLogColumns(); } } }