Java tutorial
/* * TracerFrame.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package tracer.application; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.pdf.DefaultFontMapper; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfTemplate; import com.lowagie.text.pdf.PdfWriter; import dr.app.gui.FileDrop; import dr.app.gui.chart.ChartRuntimeException; import dr.app.gui.table.TableEditorStopper; import dr.app.gui.util.LongTask; import dr.app.util.OSType; import dr.inference.trace.*; import jam.framework.DocumentFrame; import jam.panels.ActionPanel; import jam.table.TableRenderer; import jam.toolbar.Toolbar; import tracer.analysis.*; import tracer.traces.CombinedTraces; import tracer.traces.FilterDialog; import tracer.traces.FilterListPanel; import tracer.traces.TracePanel; import javax.swing.*; import javax.swing.border.Border; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.plaf.BorderUIResource; import javax.swing.table.AbstractTableModel; import javax.swing.table.JTableHeader; import java.awt.*; import java.awt.event.*; import java.awt.geom.Rectangle2D; import java.io.*; import java.text.DecimalFormat; import java.util.*; import java.util.List; public class TracerFrame extends DocumentFrame implements TracerFileMenuHandler, AnalysisMenuHandler { private final String[] columnToolTips = { null, null, null, "Trace Type: real(R), ordinal(O) or categorical(C)" }; private TracePanel tracePanel = null; private JTable traceTable = null; private TraceTableModel traceTableModel = null; private JSplitPane splitPane1 = null; private JPanel topPanel = null; private JTable statisticTable = null; private StatisticTableModel statisticTableModel = null; private JScrollPane scrollPane1 = null; private JScrollPane scrollPane2 = null; private JLabel progressLabel; private JProgressBar progressBar; private final List<LogFileTraces> traceLists = new ArrayList<LogFileTraces>(); private final List<TraceList> currentTraceLists = new ArrayList<TraceList>(); // allTraceLists not used except deleting and adding log, traceLists did all jobs // private final List<TraceList> allTraceLists = new ArrayList<TraceList>(); private CombinedTraces combinedTraces = null; private List<String> commonTraceNames = new ArrayList<String>(); private boolean homogenousTraceFiles = true; private JButton realButton; private JButton integerButton; private JButton categoricalButton; // private final List<FilterListPanel> filterListPanelList = new ArrayList<FilterListPanel>(); // private final JComboBox filterCombo = new JComboBox(new String[]{"None"}); private final JLabel filterStatus = new JLabel(); String message = ""; private int dividerLocation = -1; private DemographicDialog demographicDialog = null; private BayesianSkylineDialog bayesianSkylineDialog = null; private ExtendedBayesianSkylineDialog extendedBayesianSkylineDialog = null; private GMRFSkyrideDialog gmrfSkyrideDialog = null; private SkyGridDialog skyGridDialog = null; private TimeDensityDialog timeDensityDialog = null; private LineagesThroughTimeDialog lineagesThroughTimeDialog = null; private TraitThroughTimeDialog traitThroughTimeDialog = null; private NewTemporalAnalysisDialog createTemporalAnalysisDialog = null; // private FilterDialog filterDialog; public TracerFrame(String title) { super(); setTitle(title); getOpenAction().setEnabled(false); getSaveAction().setEnabled(false); getSaveAsAction().setEnabled(false); getCutAction().setEnabled(false); getCopyAction().setEnabled(false); getPasteAction().setEnabled(false); getDeleteAction().setEnabled(false); getSelectAllAction().setEnabled(false); getFindAction().setEnabled(false); getZoomWindowAction().setEnabled(false); AbstractAction importAction = new AbstractAction("Import Trace File...") { public void actionPerformed(ActionEvent ae) { doImport(); } }; setImportAction(importAction); setExportAction(exportDataTableAction); setAnalysesEnabled(false); } public void initializeComponents() { setSize(new java.awt.Dimension(1200, 800)); tracePanel = new TracePanel(this); tracePanel.setBorder(new BorderUIResource.EmptyBorderUIResource(new java.awt.Insets(12, 6, 12, 12))); traceTableModel = new TraceTableModel(); traceTable = new JTable(traceTableModel) { //Implement table cell tool tips. public String getToolTipText(MouseEvent e) { java.awt.Point p = e.getPoint(); return traceTableModel.getToolTipText(rowAtPoint(p), columnAtPoint(p)); } }; TableRenderer renderer = new TableRenderer(SwingConstants.LEFT, new Insets(0, 4, 0, 4)); traceTable.getColumnModel().getColumn(0).setCellRenderer(renderer); traceTable.getColumnModel().getColumn(1).setPreferredWidth(50); traceTable.getColumnModel().getColumn(1).setCellRenderer(renderer); traceTable.getColumnModel().getColumn(2).setPreferredWidth(50); traceTable.getColumnModel().getColumn(2).setCellRenderer(renderer); traceTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); traceTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { // if(!evt.getValueIsAdjusting()) traceTableSelectionChanged(); } }); scrollPane1 = new JScrollPane(traceTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); ActionPanel actionPanel1 = new ActionPanel(false); actionPanel1.setAddAction(getImportAction()); actionPanel1.setRemoveAction(getRemoveTraceAction()); getRemoveTraceAction().setEnabled(false); Toolbar controlPanel1 = new Toolbar(); JButton reloadButton = new JButton(getReloadAction()); reloadButton.setText("Reload"); PanelUtils.setupComponent(reloadButton); reloadButton.setToolTipText("Reload the selected log file(s)"); getReloadAction().setEnabled(false); controlPanel1.add(actionPanel1); controlPanel1.addFlexibleSpace(); controlPanel1.add(reloadButton); controlPanel1.setFloatable(false); controlPanel1.setBorder(BorderFactory.createEmptyBorder()); topPanel = new JPanel(new BorderLayout(0, 0)); topPanel.setBorder(new BorderUIResource.EmptyBorderUIResource(new java.awt.Insets(0, 0, 6, 0))); topPanel.add(new JLabel("Trace Files:"), BorderLayout.NORTH); topPanel.add(scrollPane1, BorderLayout.CENTER); topPanel.add(controlPanel1, BorderLayout.SOUTH); statisticTableModel = new StatisticTableModel(); statisticTable = new JTable(statisticTableModel) { //Implement table header tool tips. protected JTableHeader createDefaultTableHeader() { return new JTableHeader(columnModel) { public String getToolTipText(MouseEvent e) { java.awt.Point p = e.getPoint(); int index = columnModel.getColumnIndexAtX(p.x); int realIndex = columnModel.getColumn(index).getModelIndex(); return columnToolTips[realIndex]; } }; } }; statisticTable.getColumnModel().getColumn(0).setPreferredWidth(150); statisticTable.getColumnModel().getColumn(0).setCellRenderer(renderer); statisticTable.getColumnModel().getColumn(1).setPreferredWidth(70); statisticTable.getColumnModel().getColumn(1).setCellRenderer(renderer); statisticTable.getColumnModel().getColumn(2).setPreferredWidth(70); statisticTable.getColumnModel().getColumn(2).setCellRenderer(renderer); // ComboBoxRenderer comboBoxRenderer = new ComboBoxRenderer(TraceFactory.TraceType.values()); // comboBoxRenderer.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); statisticTable.getColumnModel().getColumn(3).setPreferredWidth(20); statisticTable.getColumnModel().getColumn(3).setCellRenderer(renderer); statisticTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); statisticTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { if (!evt.getValueIsAdjusting()) statisticTableSelectionChanged(); } }); TableEditorStopper.ensureEditingStopWhenTableLosesFocus(statisticTable); scrollPane2 = new JScrollPane(statisticTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel bottomPanel = new JPanel(new BorderLayout(0, 0)); // bottomPanel.setBorder(new BorderUIResource.EmptyBorderUIResource(new java.awt.Insets(6, 0, 0, 0))); bottomPanel.add(new JLabel("Traces:"), BorderLayout.NORTH); bottomPanel.add(scrollPane2, BorderLayout.CENTER); JPanel changeTraceTypePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); changeTraceTypePanel.add(new JLabel("Type:")); realButton = new JButton("(R)eal"); PanelUtils.setupComponent(realButton); realButton.setToolTipText(TraceType.REAL.toString()); realButton.setFont(UIManager.getFont("SmallSystemFont")); realButton.setEnabled(false); integerButton = new JButton("(I)nt"); PanelUtils.setupComponent(integerButton); integerButton.setToolTipText(TraceType.INTEGER.toString()); integerButton.setFont(UIManager.getFont("SmallSystemFont")); integerButton.setEnabled(false); categoricalButton = new JButton("(C)at"); PanelUtils.setupComponent(categoricalButton); categoricalButton.setToolTipText(TraceType.CATEGORICAL.toString()); categoricalButton.setFont(UIManager.getFont("SmallSystemFont")); categoricalButton.setEnabled(false); JLabel constantLabel = new JLabel("* constant"); PanelUtils.setupComponent(constantLabel); constantLabel.setFont(UIManager.getFont("SmallSystemFont")); realButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeTraceType(TraceType.REAL); } }); integerButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeTraceType(TraceType.INTEGER); } }); categoricalButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { changeTraceType(TraceType.CATEGORICAL); } }); changeTraceTypePanel.add(realButton); changeTraceTypePanel.add(integerButton); changeTraceTypePanel.add(categoricalButton); changeTraceTypePanel.add(constantLabel); changeTraceTypePanel.setToolTipText("<html> Change the data type of a selected parameter here. <br>" + "Alternatively use key word real, ordinal, binary, categorical " + "followed by tab delimited column names <br> in the beginning of the log file, " + "to define the trace type. For example: <br> # integer columnName1 columnName2 ... </html>"); bottomPanel.add(changeTraceTypePanel, BorderLayout.SOUTH); JPanel leftPanel = new JPanel(new BorderLayout(0, 0)); leftPanel.setPreferredSize(new Dimension(400, 300)); splitPane1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, topPanel, bottomPanel); splitPane1.setBorder(null); JPanel progressPanel = new JPanel(new BorderLayout(0, 0)); progressLabel = new JLabel(""); progressBar = new JProgressBar(); progressPanel.add(progressLabel, BorderLayout.NORTH); progressPanel.add(progressBar, BorderLayout.CENTER); progressPanel.setBorder(new BorderUIResource.EmptyBorderUIResource(new java.awt.Insets(6, 0, 0, 0))); leftPanel.add(splitPane1, BorderLayout.CENTER); leftPanel.add(progressPanel, BorderLayout.SOUTH); leftPanel.setBorder(new BorderUIResource.EmptyBorderUIResource(new java.awt.Insets(12, 12, 12, 6))); JSplitPane splitPane2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, leftPanel, tracePanel); splitPane2.setBorder(null); splitPane2.setDividerLocation(350); Color focusColor = UIManager.getColor("Focus.color"); Border focusBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, focusColor); splitPane1.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); new FileDrop(null, splitPane1, focusBorder, new FileDrop.Listener() { public void filesDropped(java.io.File[] files) { importFiles(files); } // end filesDropped }); // end FileDrop.Listener getContentPane().setLayout(new java.awt.BorderLayout(0, 0)); getContentPane().add(splitPane2, BorderLayout.CENTER); splitPane1.setDividerLocation(2000); } private void changeTraceType(TraceType newType) { int[] selectedTraceFiles = traceTable.getSelectedRows(); int[] selectedStatistics = statisticTable.getSelectedRows(); boolean combinedTracesSelected = selectedTraceFiles[selectedTraceFiles.length - 1] == traceLists.size(); List<LogFileTraces> selectedTraceLists = new ArrayList<LogFileTraces>(); if (combinedTracesSelected) { selectedTraceLists.addAll(traceLists); } else { for (int row : selectedTraceFiles) { selectedTraceLists.add(traceLists.get(row)); } } for (LogFileTraces tl : selectedTraceLists) { for (int row : selectedStatistics) { int id = tl.getTraceIndex(commonTraceNames.get(row)); try { tl.changeTraceType(id, newType); } catch (TraceException e) { JOptionPane.showMessageDialog(this, e, "Trace Type Exception in " + tl.getName(), JOptionPane.ERROR_MESSAGE); } tl.analyseTrace(id); } } updateCombinedTraces(); statisticTableModel.fireTableDataChanged(); traceTableModel.fireTableDataChanged(); // selection will be lost by fireTableDataChanged so reselect them statisticTable.getSelectionModel().clearSelection(); for (int row : selectedStatistics) { statisticTable.getSelectionModel().addSelectionInterval(row, row); } traceTable.getSelectionModel().clearSelection(); for (int row : selectedTraceFiles) { traceTable.getSelectionModel().addSelectionInterval(row, row); } //traceTableSelectionChanged(); //statisticTableSelectionChanged(); } public void setVisible(boolean b) { super.setVisible(b); setupDividerLocation(); } private void setupDividerLocation() { if (dividerLocation == -1 || dividerLocation == splitPane1.getDividerLocation()) { int h0 = topPanel.getHeight(); int h1 = scrollPane1.getViewport().getHeight(); int h2 = traceTable.getPreferredSize().height; dividerLocation = h2 + h0 - h1; // int h0 = topPanel.getHeight() - scrollPane1.getViewport().getHeight(); // dividerLocation = traceTable.getPreferredSize().height + h0; if (dividerLocation > 400) dividerLocation = 400; splitPane1.setDividerLocation(dividerLocation); } } public void setAnalysesEnabled(boolean enabled) { getDemographicAction().setEnabled(enabled); getBayesianSkylineAction().setEnabled(enabled); getGMRFSkyrideAction().setEnabled(enabled); getSkyGridAction().setEnabled(enabled); getLineagesThroughTimeAction().setEnabled(enabled); getCreateTemporalAnalysisAction().setEnabled(enabled); getAddDemographicAction().setEnabled(enabled && temporalAnalysisFrame != null); getAddBayesianSkylineAction().setEnabled(enabled && temporalAnalysisFrame != null); getAddTimeDensityAction().setEnabled(enabled && temporalAnalysisFrame != null); getConditionalPosteriorDistAction().setEnabled(enabled); getExportAction().setEnabled(enabled); getExportRawDataAction().setEnabled(enabled); getExportDataTableAction().setEnabled(enabled); // getExportFullStatisticsAction().setEnabled(enabled); getExportPDFAction().setEnabled(enabled); getCopyAction().setEnabled(true); } public void checkForUniqueNames(LogFileTraces traceList) { Map<String, Trace> nameMap = new HashMap<String, Trace>(); Map<String, Integer> nameNumberMap = new HashMap<String, Integer>(); for (int i = 0; i < traceList.getTraceCount(); i++) { Trace trace = traceList.getTrace(i); String name = trace.getName(); Trace lastTrace = nameMap.get(name); if (lastTrace == null) { nameMap.put(name, trace); nameNumberMap.put(name, 1); } else { int number = nameNumberMap.get(name); if (number == 1) { lastTrace.setName(name + "_" + number); } number += 1; trace.setName(name + "_" + number); nameNumberMap.put(name, number); } } } public void addTraceList(LogFileTraces traceList) { int[] selRows = traceTable.getSelectedRows(); traceLists.add(traceList); updateCombinedTraces(); setAnalysesEnabled(true); traceTableModel.fireTableDataChanged(); int newRow = traceLists.size() - 1; traceTable.getSelectionModel().setSelectionInterval(newRow, newRow); if (selRows.length > 1) { for (int row : selRows) { if (row == traceLists.size() - 1) { row = traceLists.size(); } traceTable.getSelectionModel().addSelectionInterval(row, row); } } setupDividerLocation(); // allTraceLists.add(traceList); } private LogFileTraces[] removeTraceList() { int[] selRows = traceTable.getSelectedRows(); LogFileTraces[] tls = new LogFileTraces[selRows.length]; int i = 0; for (int row : selRows) { tls[i] = traceLists.get(row); i++; } for (LogFileTraces tl : tls) { traceLists.remove(tl); // allTraceLists.remove(tl); } updateCombinedTraces(); traceTableModel.fireTableDataChanged(); statisticTableModel.fireTableDataChanged(); if (traceLists.size() == 0) { getRemoveTraceAction().setEnabled(false); setAnalysesEnabled(false); currentTraceLists.clear(); // allTraceLists.clear(); statisticTableModel.fireTableDataChanged(); tracePanel.setTraces(null, null); } tracePanel.traceRemoved(); if (traceLists.size() > 0) { int row = selRows[0]; if (row >= traceLists.size()) { row = traceLists.size() - 1; } traceTable.getSelectionModel().addSelectionInterval(row, row); } setupDividerLocation(); return tls; } // reload all logs private void refreshTraceList() { final int[] statsSelRows = statisticTable.getSelectedRows(); Rectangle rect = statisticTable.getVisibleRect(); int firstRow = statisticTable.rowAtPoint(rect.getLocation()); double numberOfRows = rect.getHeight() / statisticTable.getRowHeight(); int lastRow = firstRow + (int) Math.floor(numberOfRows); statisticTableModel.setFirstVisibleRow(firstRow); statisticTableModel.setLastVisibleRow(lastRow); LogFileTraces[] tls = removeTraceList(); if (tls.length > 0) { final LogFileTraces[] newTls = new LogFileTraces[tls.length]; for (int i = 0; i < tls.length; i++) { newTls[i] = new LogFileTraces(tls[i].getName(), tls[i].getFile()); } SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { processTraces(newTls); return null; } @Override protected void done() { updateCombinedTraces(); statisticTableModel.fireTableDataChanged(); statisticTable.getSelectionModel().clearSelection(); for (int row : statsSelRows) { statisticTable.getSelectionModel().addSelectionInterval(row, row); } traceTableSelectionChanged(); statisticTableSelectionChanged(); } }; worker.execute(); // updateCombinedTraces(); // // statisticTableModel.fireTableDataChanged(); // statisticTable.getSelectionModel().clearSelection(); // for (int row : statsSelRows) { // statisticTable.getSelectionModel().addSelectionInterval(row, row); // } // traceTableSelectionChanged(); // statisticTableSelectionChanged(); } } public void setBurnIn(int index, long burnIn) { LogFileTraces trace = traceLists.get(index); trace.setBurnIn(burnIn); analyseTraceList(trace); updateCombinedTraces(); updateTraceTables(); } public void updateCombinedTraces() { if (traceLists.size() > 1) { LogFileTraces[] traces = new LogFileTraces[traceLists.size()]; try { traceLists.toArray(traces); } catch (ArrayStoreException ase) { combinedTraces = null; // JOptionPane.showMessageDialog(this, "", // "Trace Type Exception", // JOptionPane.WARNING_MESSAGE); } try { combinedTraces = new CombinedTraces("Combined", traces); analyseTraceList(combinedTraces); } catch (TraceException te) { combinedTraces = null; // validations in CombinedTraces() } } else { combinedTraces = null; } } public void updateTraceTables() { int[] selectedTraces = traceTable.getSelectedRows(); int[] selectedStatistics = statisticTable.getSelectedRows(); traceTableModel.fireTableDataChanged(); statisticTableModel.fireTableDataChanged(); traceTable.getSelectionModel().clearSelection(); for (int row : selectedTraces) { traceTable.getSelectionModel().addSelectionInterval(row, row); } statisticTable.getSelectionModel().clearSelection(); for (int row : selectedStatistics) { statisticTable.getSelectionModel().addSelectionInterval(row, row); } } public void traceTableSelectionChanged() { if (traceLists.size() == 0) { return; } int[] selRows = traceTable.getSelectedRows(); if (selRows.length == 0) { getRemoveTraceAction().setEnabled(false); getReloadAction().setEnabled(false); setAnalysesEnabled(false); return; } setAnalysesEnabled(true); getRemoveTraceAction().setEnabled(true); getReloadAction().setEnabled(true); currentTraceLists.clear(); // Check for and add the combined trace first so it is underneath the // individual traces. for (int row : selRows) { if (row == traceLists.size()) { // Combined is include in the selection so disable remove getRemoveTraceAction().setEnabled(false); getReloadAction().setEnabled(false); currentTraceLists.add(combinedTraces); } } // Get the common set of trace names. This is slightly more complicated // that it may seem because we want to keep them in order of the first // selected trace file (i.e., as a list). So we populate the list with the // first trace file, collect the common set, and then retain only those in // the set. commonTraceNames.clear(); homogenousTraceFiles = true; Set<String> commonSet = new HashSet<String>(); boolean isFirst = true; for (int row : selRows) { if (row < traceLists.size()) { TraceList tl = traceLists.get(row); Set<String> nameSet = new HashSet<String>(); for (int i = 0; i < tl.getTraceCount(); i++) { String traceName = tl.getTraceName(i); nameSet.add(traceName); if (isFirst) { // add them in order of the first trace file commonTraceNames.add(traceName); } } if (isFirst) { commonSet.addAll(nameSet); isFirst = false; } else { if (nameSet.size() != commonSet.size()) { homogenousTraceFiles = false; } commonSet.retainAll(nameSet); } currentTraceLists.add(tl); } else if (isFirst) { // if the 'Combined' trace is selected but no other trace files, then add all traces TraceList tl = traceLists.get(0); Set<String> nameSet = new HashSet<String>(); for (int i = 0; i < tl.getTraceCount(); i++) { String traceName = tl.getTraceName(i); nameSet.add(traceName); commonTraceNames.add(traceName); } commonSet.addAll(nameSet); } } commonTraceNames.retainAll(commonSet); int[] rows = statisticTable.getSelectedRows(); statisticTableModel.fireTableDataChanged(); if (rows.length > 0) { for (int row : rows) { statisticTable.getSelectionModel().addSelectionInterval(row, row); } statisticTable.scrollRectToVisible( statisticTable.getCellRect(statisticTableModel.getLastVisibleRow(), 0, true)); } else { statisticTable.getSelectionModel().setSelectionInterval(0, 0); } filterStatus.setText(message); } // private String updateStatusMessage(List<TraceList> currentTraceLists) { // String message = ""; // List<String> traceNameList = new ArrayList<String>(); // List<String> messageList = new ArrayList<String>(); // //// for (int i = 0; i < currentTraceLists.size(); i++) { //// FilteredTraceList fTL = (FilteredTraceList) currentTraceLists.get(i); //// Filter f = ).getTraceName(); //// //// if (f != null) { //// String tN = f.getTraceName(); //// if (!traceNameList.contains(tN)) { //// traceNameList.add(tN); //// message = f.getStatusMessage() + " in file(s) " + "\'" + fTL.getName() + "\'"; //// messageList.add(message); //// } else { //// int id = traceNameList.indexOf(tN); //// message = messageList.get(id) + " and \'" + fTL.getName() + "\'"; //// messageList.set(id, message); //// } //// //// filterCombo.setSelectedItem(tN); // todo //// } //// } // // // message = ""; // // for (String s : messageList) { // message += s + "; "; // } // // return message; // } // private void getIntersectionOfSelectedTraceLists() { // filterCombo.removeAllItems(); // filterCombo.addItem("None"); // //// Map<String, Class> tracesIntersection = new HashMap<String, Class>(); //names have no order // List<String> tracesIntersection = Collections.synchronizedList(new ArrayList<String>()); // List<TraceFactory.TraceType> tracesIntersectionClass = Collections.synchronizedList(new ArrayList<TraceFactory.TraceType>()); // List<String> incompatibleTrace = Collections.synchronizedList(new ArrayList<String>()); // for (TraceList tl : currentTraceLists) { // List<String> currentTrace = new ArrayList<String>(); // for (int i = 0; i < tl.getTraceCount(); i++) { // String traceName = tl.getTraceName(i); // currentTrace.add(traceName); // if (!incompatibleTrace.contains(traceName)) { // TraceFactory.TraceType traceType = tl.getTrace(i).getTraceType(); // if (traceType == null) { // incompatibleTrace.add(traceName); // break; // } // // if (tracesIntersection.contains(traceName)) { // if (traceType != tracesIntersectionClass.get(tracesIntersection.indexOf(traceName))) { // tracesIntersectionClass.remove(tracesIntersection.indexOf(traceName)); // tracesIntersection.remove(traceName); // incompatibleTrace.add(traceName); // break; // } // // } else if (currentTraceLists.indexOf(tl) == 0) { // // tracesIntersection.add(traceName); // tracesIntersectionClass.add(traceType); // } // } // } // end i loop // // for (String traceName : tracesIntersection) { // if (!currentTrace.contains(traceName)) { // tracesIntersectionClass.remove(tracesIntersection.indexOf(traceName)); // tracesIntersection.remove(traceName); // incompatibleTrace.add(traceName); // } // } // // } // // assert (tracesIntersection.size() == tracesIntersectionClass.size()); // // if (!tracesIntersection.isEmpty()) { // for (String traceName : tracesIntersection) { // filterCombo.addItem(traceName); // } // } // } public void statisticTableSelectionChanged() { int[] selRows = statisticTable.getSelectedRows(); boolean isIncomplete = false; for (TraceList tl : currentTraceLists) { if (tl == null || tl.getTraceCount() == 0 || tl.getStateCount() == 0) isIncomplete = true; } List<String> selectedTraces = getSelectedTraces(); if (currentTraceLists.size() == 0 || isIncomplete) { tracePanel.setTraces(null, selectedTraces); } else { TraceList[] tl = new TraceList[currentTraceLists.size()]; currentTraceLists.toArray(tl); try { tracePanel.setTraces(tl, selectedTraces); } catch (ChartRuntimeException cre) { JOptionPane.showMessageDialog(this, "One or more traces contain invalid values and \rare not able to be displayed.", "Problem reading trace file", JOptionPane.ERROR_MESSAGE); } } realButton.setEnabled(selRows.length > 0); integerButton.setEnabled(selRows.length > 0); categoricalButton.setEnabled(selRows.length > 0); } public List<String> getSelectedTraces() { int[] selRows = statisticTable.getSelectedRows(); List<String> selectedTraces = new ArrayList<String>(); for (int selRow : selRows) { if (selRow < commonTraceNames.size()) { selectedTraces.add(commonTraceNames.get(selRow)); } } if (selectedTraces.size() < 1) { selectedTraces.add(commonTraceNames.get(0)); } return selectedTraces; } public void analyseTraceList(TraceList job) { if (analyseTask == null) { analyseTask = new AnalyseTraceTask(); javax.swing.Timer timer = new javax.swing.Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent evt) { progressBar.setMaximum(analyseTask.getLengthOfTask()); progressBar.setValue(analyseTask.getCurrent()); } }); analyseTask.go(); timer.start(); } analyseTask.add(job); } AnalyseTraceTask analyseTask = null; class AnalyseTraceTask extends LongTask { class AnalysisStack<T> { private final java.util.List<T> jobs = new ArrayList<T>(); public synchronized void add(T job) { jobs.add(job); } public synchronized int getCount() { return jobs.size(); } public synchronized T get(int index) { return jobs.get(index); } public synchronized void remove(int index) { jobs.remove(index); } } private final AnalysisStack<TraceList> analysisStack = new AnalysisStack<TraceList>(); public AnalyseTraceTask() { } public void add(TraceList job) { analysisStack.add(job); current = 0; } public int getCurrent() { return current; } public int getLengthOfTask() { int count = 0; for (int i = 0; i < analysisStack.getCount(); i++) { count += analysisStack.get(i).getTraceCount(); } return count; } public void stop() { } public boolean done() { return false; } public String getDescription() { return "Analysing Trace File..."; } public String getMessage() { return null; } public Object doWork() { current = 0; boolean textCleared = true; do { if (analysisStack.getCount() > 0) { Object job = analysisStack.get(0); TraceList tl = (TraceList) job; try { for (int i = 0; i < tl.getTraceCount(); i++) { progressLabel.setText("Analysing " + tl.getName() + ":"); textCleared = false; tl.analyseTrace(i); repaint(); current += 1; } } catch (final Exception ex) { // do nothing. An exception is sometimes fired when burnin is changed whilst in the // middle of an analysis. This doesn't seem to matter as the analysis is restarted. ex.printStackTrace(); // EventQueue.invokeLater ( // new Runnable () { // public void run () { // JOptionPane.showMessageDialog(TracerFrame.this, "Fatal exception: " + ex.getMessage(), // "Error reading file", // JOptionPane.ERROR_MESSAGE); // } // }); } analysisStack.remove(0); } else { if (!textCleared) { progressLabel.setText(""); textCleared = true; } try { Thread.sleep(500); } catch (InterruptedException ie) { // do nothing } } } while (true); } //private int lengthOfTask = 0; private int current = 0; //private String message; } public final void doExportData(boolean rawData) { FileDialog dialog = new FileDialog(this, (rawData ? "Export Raw Data..." : "Export Data Table..."), FileDialog.SAVE); dialog.setVisible(true); if (dialog.getFile() != null) { File file = new File(dialog.getDirectory(), dialog.getFile()); try { FileWriter writer = new FileWriter(file); if (rawData) { try { exportRawData(new PrintWriter(writer)); } catch (StateStepsDifferentException ssde) { JOptionPane.showMessageDialog(this, "Unable to write multiple trace files\n" + "with different step sizes.", "Unable to write file", JOptionPane.ERROR_MESSAGE); } } else { writer.write(tracePanel.getExportDataTableText()); } writer.close(); } catch (IOException ioe) { JOptionPane.showMessageDialog(this, "Unable to write file: " + ioe, "Unable to write file", JOptionPane.ERROR_MESSAGE); } } } private class StateStepsDifferentException extends Exception { } /** * Write out the selected traces to a single file. Checks that when multiple files are * selected they have the same step size. * @param writer */ private void exportRawData(PrintWriter writer) throws StateStepsDifferentException { List<String> selectedTraces = getSelectedTraces(); long minStateStart = Long.MAX_VALUE; long maxStateCount = 0; long stateStep = 0; for (TraceList tl : currentTraceLists) { long stateCount = tl.getStateCount(); if (stateStep == 0) { stateStep = tl.getStepSize(); } else { if (stateStep != tl.getStepSize()) { throw new StateStepsDifferentException(); } } if (tl.getBurnIn() < minStateStart) { minStateStart = tl.getBurnIn(); } if (stateCount > maxStateCount) { maxStateCount = stateCount; } } writer.print("state"); for (String traceName : selectedTraces) { for (TraceList tl : currentTraceLists) { String name = tl.getName() + ":" + tl.getTraceName(tl.getTraceIndex(traceName)); writer.print("\t"); writer.print(name); } } writer.println(); for (long state = minStateStart; state <= maxStateCount; state += stateStep) { writer.print(state); for (String traceName : selectedTraces) { for (TraceList tl : currentTraceLists) { int traceIndex = tl.getTraceIndex(traceName); Trace trace = tl.getTrace(traceIndex); writer.print("\t"); long burnin = tl.getBurnIn(); int index = (int) ((state - burnin) / stateStep); if (state >= burnin && index < trace.getValueCount()) { double value = trace.getValue(index); String valueString; if (trace.getTraceType().isDiscrete()) { if (trace.getTraceType().isCategorical()) { valueString = trace.getCategoryLabelMap().get((int) value); } else { valueString = Integer.toString((int) value); } } else { valueString = Double.toString(value); } writer.print(valueString); } else { // print nothing in this cell } } } writer.println(); } } /** * export full statistic summary of selected traceList (log) to a tab-delimited txt file */ // public final void doExportStatisticSummary() { // final JFrame frame = this; // // FileDialog dialog = new FileDialog(frame, "Export Statistic Summary...", FileDialog.SAVE); // // dialog.setVisible(true); // if (dialog.getFile() != null) { // File file = new File(dialog.getDirectory(), dialog.getFile()); // // // todo use LongTask // final String statSummTxt = TraceAnalysis.getStatisticSummary(currentTraceLists); // // try { // // FileWriter writer = new FileWriter(file); // writer.write(statSummTxt); // writer.close(); // // } catch (IOException ioe) { // JOptionPane.showMessageDialog(this, "Unable to write file: " + ioe, // "Unable to write file", // JOptionPane.ERROR_MESSAGE); // } // } // } public final void doExportPDF() { FileDialog dialog = new FileDialog(this, "Export PDF Image...", FileDialog.SAVE); dialog.setVisible(true); if (dialog.getFile() != null) { File file = new File(dialog.getDirectory(), dialog.getFile()); Rectangle2D bounds = tracePanel.getExportableComponent().getBounds(); Document document = new Document( new com.lowagie.text.Rectangle((float) bounds.getWidth(), (float) bounds.getHeight())); try { // step 2 PdfWriter writer; writer = PdfWriter.getInstance(document, new FileOutputStream(file)); // step 3 document.open(); // step 4 PdfContentByte cb = writer.getDirectContent(); PdfTemplate tp = cb.createTemplate((float) bounds.getWidth(), (float) bounds.getHeight()); Graphics2D g2d = tp.createGraphics((float) bounds.getWidth(), (float) bounds.getHeight(), new DefaultFontMapper()); tracePanel.getExportableComponent().print(g2d); g2d.dispose(); cb.addTemplate(tp, 0, 0); } catch (DocumentException de) { JOptionPane.showMessageDialog(this, "Error writing PDF file: " + de, "Export PDF Error", JOptionPane.ERROR_MESSAGE); } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(this, "Error writing PDF file: " + e, "Export PDF Error", JOptionPane.ERROR_MESSAGE); } document.close(); } } public final void doImport() { if (OSType.isMac()) { FileDialog dialog = new FileDialog(this, "Import trace file...", FileDialog.LOAD); dialog.setVisible(true); if (dialog.getFile() != null) { importFiles(new File[] { new File(dialog.getDirectory(), dialog.getFile()) }); } } else { final JFileChooser chooser = new JFileChooser(openDefaultDirectory); chooser.setMultiSelectionEnabled(true); FileNameExtensionFilter filter = new FileNameExtensionFilter("BEAST log (*.log) Files", "log", "txt"); chooser.setFileFilter(filter); final int returnVal = chooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File[] files = chooser.getSelectedFiles(); importFiles(files); } } } private void importFiles(File[] files) { LogFileTraces[] traces = new LogFileTraces[files.length]; for (int i = 0; i < files.length; i++) { traces[i] = new LogFileTraces(files[i].getName(), files[i]); } processTraces(traces); } private File openDefaultDirectory = null; private void setDefaultDir(File file) { final String s = file.getAbsolutePath(); String p = s.substring(0, s.length() - file.getName().length()); openDefaultDirectory = new File(p); if (!openDefaultDirectory.isDirectory()) { openDefaultDirectory = null; } } protected void processTraces(final LogFileTraces[] tracesArray) { final JFrame frame = this; // set default dir to directory of last file setDefaultDir(tracesArray[tracesArray.length - 1].getFile()); if (tracesArray.length == 1) { try { final LogFileTraces traces = tracesArray[0]; final ProgressMonitorInputStream in = new ProgressMonitorInputStream(this, "Reading " + traces.getName(), new FileInputStream(traces.getFile())); in.getProgressMonitor().setMillisToDecideToPopup(0); in.getProgressMonitor().setMillisToPopup(0); // final Reader reader = new InputStreamReader(in); Thread readThread = new Thread() { public void run() { try { traces.loadTraces(in); EventQueue.invokeLater(new Runnable() { public void run() { analyseTraceList(traces); checkForUniqueNames(traces); addTraceList(traces); } }); } catch (final TraceException te) { EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, "Problem with trace file: " + te.getMessage(), "Problem with trace file", JOptionPane.ERROR_MESSAGE); } }); } catch (final InterruptedIOException iioex) { // The cancel dialog button was pressed - do nothing } catch (final IOException ioex) { EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, "File I/O Error: " + ioex.getMessage(), "File I/O Error", JOptionPane.ERROR_MESSAGE); } }); } } }; readThread.start(); } catch (FileNotFoundException fnfe) { JOptionPane.showMessageDialog(this, "Unable to open file: File not found", "Unable to open file", JOptionPane.ERROR_MESSAGE); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Fatal exception: " + ex, "Error reading file", JOptionPane.ERROR_MESSAGE); } } else { Thread readThread = new Thread() { public void run() { try { for (final LogFileTraces traces : tracesArray) { // final Reader reader = new FileReader(traces.getFile()); traces.loadTraces(); EventQueue.invokeLater(new Runnable() { public void run() { analyseTraceList(traces); addTraceList(traces); } }); } } catch (final TraceException te) { EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, "Problem with trace file: " + te.getMessage(), "Problem with trace file", JOptionPane.ERROR_MESSAGE); } }); } catch (final InterruptedIOException iioex) { // The cancel dialog button was pressed - do nothing } catch (final IOException ioex) { EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, "File I/O Error: " + ioex.getMessage(), "File I/O Error", JOptionPane.ERROR_MESSAGE); } }); // } catch (final Exception ex) { // EventQueue.invokeLater ( // new Runnable () { // public void run () { // JOptionPane.showMessageDialog(frame, "Fatal exception: " + ex.getMessage(), // "Error reading file", // JOptionPane.ERROR_MESSAGE); // } // }); } } }; readThread.start(); } } protected boolean readFromFile(File file) throws IOException { throw new RuntimeException("Cannot read file - use import instead"); } protected boolean writeToFile(File file) { throw new RuntimeException("Cannot write file - this is a read-only application"); } public void doCopy() { tracePanel.doCopy(); } private TemporalAnalysisFrame temporalAnalysisFrame = null; private void doCreateTemporalAnalysis() { if (createTemporalAnalysisDialog == null) { createTemporalAnalysisDialog = new NewTemporalAnalysisDialog(this); } if (createTemporalAnalysisDialog.showDialog() == JOptionPane.CANCEL_OPTION) { return; } temporalAnalysisFrame = createTemporalAnalysisDialog.createTemporalAnalysisFrame(this); createTemporalAnalysisAction.setEnabled(false); addExtendedBayesianSkylineAction.setEnabled(true); addBayesianSkylineAction.setEnabled(true); addDemographicAction.setEnabled(true); addTimeDensity.setEnabled(true); temporalAnalysisFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { temporalAnalysisFrame = null; createTemporalAnalysisAction.setEnabled(true); addBayesianSkylineAction.setEnabled(false); addDemographicAction.setEnabled(false); addTimeDensity.setEnabled(false); } }); } public void doDemographic(boolean add) { if (demographicDialog == null) { demographicDialog = new DemographicDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, or select the Combined trace.", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); return; } if (add) { if (demographicDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } demographicDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (demographicDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } demographicDialog.createDemographicFrame(currentTraceLists.get(0), this); } } public void doBayesianSkyline(boolean add) { if (bayesianSkylineDialog == null) { bayesianSkylineDialog = new BayesianSkylineDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); return; } if (add) { if (bayesianSkylineDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } bayesianSkylineDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (bayesianSkylineDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } bayesianSkylineDialog.createBayesianSkylineFrame(currentTraceLists.get(0), this); } } public void doExtendedBayesianSkyline(boolean add) { if (extendedBayesianSkylineDialog == null) { extendedBayesianSkylineDialog = new ExtendedBayesianSkylineDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); return; } if (add) { if (extendedBayesianSkylineDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } extendedBayesianSkylineDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (extendedBayesianSkylineDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } extendedBayesianSkylineDialog.createExtendedBayesianSkylineFrame(currentTraceLists.get(0), this); } } public void doSkyGrid(boolean add) { if (skyGridDialog == null) { skyGridDialog = new SkyGridDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); return; } if (add) { if (skyGridDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } skyGridDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (skyGridDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } skyGridDialog.createSkyGridFrame(currentTraceLists.get(0), this); } } public void doGMRFSkyride(boolean add) { if (gmrfSkyrideDialog == null) { gmrfSkyrideDialog = new GMRFSkyrideDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); return; } if (add) { if (gmrfSkyrideDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } gmrfSkyrideDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (gmrfSkyrideDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } gmrfSkyrideDialog.createGMRFSkyrideFrame(currentTraceLists.get(0), this); } } public void doLineagesThroughTime(boolean add) { if (lineagesThroughTimeDialog == null) { lineagesThroughTimeDialog = new LineagesThroughTimeDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); } if (add) { if (lineagesThroughTimeDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } lineagesThroughTimeDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (lineagesThroughTimeDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } lineagesThroughTimeDialog.createLineagesThroughTimeFrame(currentTraceLists.get(0), this); } } public void doTraitThroughTime(boolean add) { if (traitThroughTimeDialog == null) { traitThroughTimeDialog = new TraitThroughTimeDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (but not the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); } if (add) { if (traitThroughTimeDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } traitThroughTimeDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } else { if (traitThroughTimeDialog.showDialog(currentTraceLists.get(0), null) == JOptionPane.CANCEL_OPTION) { return; } traitThroughTimeDialog.createTraitThroughTimeFrame(currentTraceLists.get(0), this); } } private void doAddTimeDensity() { if (timeDensityDialog == null) { timeDensityDialog = new TimeDensityDialog(this); } if (currentTraceLists.size() != 1) { JOptionPane.showMessageDialog(this, "Please select exactly one trace to do\n" + "this analysis on, (or the Combined trace).", "Unable to perform analysis", JOptionPane.INFORMATION_MESSAGE); } if (timeDensityDialog.showDialog(currentTraceLists.get(0), temporalAnalysisFrame) == JOptionPane.CANCEL_OPTION) { return; } timeDensityDialog.addToTemporalAnalysis(currentTraceLists.get(0), temporalAnalysisFrame); } private void doFindConditionalPosteriorDistributions() { // if (filterDialog == null) { // FilterDialog filterDialog = new FilterDialog(this); // } if (currentTraceLists == null) { JOptionPane.showMessageDialog(this, "There is no file being selected !", "Invalid Action", JOptionPane.ERROR_MESSAGE); } else if (currentTraceLists.size() > 1) { JOptionPane.showMessageDialog(this, "Only one file can be selected each time !", "Invalid Action", JOptionPane.ERROR_MESSAGE); } else if (!(currentTraceLists.get(0) instanceof FilteredTraceList)) { JOptionPane.showMessageDialog(this, "Filter cannot be applied to Combined Trace List yet !", "Invalid Action", JOptionPane.ERROR_MESSAGE); } else { FilterListPanel filterListPanel = null; if (combinedTraces == null) { filterListPanel = new FilterListPanel((FilteredTraceList) currentTraceLists.get(0)); } else { int n = JOptionPane.showConfirmDialog(this, "Because Combined Traces exits, you have to apply filter\n" + "to all files including Combined Traces.\n" + "Would you like to continue or not ?", "Combined Traces Detected", JOptionPane.YES_NO_OPTION); if (n == JOptionPane.YES_OPTION) { filterListPanel = new FilterListPanel(combinedTraces); } } if (filterListPanel != null) { try { FilterDialog filterDialog = new FilterDialog(this); message = " " + filterDialog.showDialog(filterListPanel, filterStatus.getText()); filterStatus.setText(message); } catch (RuntimeException e) { JOptionPane.showMessageDialog(this, "Error : " + e.getMessage(), "Filter Error", JOptionPane.ERROR_MESSAGE); } } } } public JComponent getExportableComponent() { return tracePanel.getExportableComponent(); } class TraceTableModel extends AbstractTableModel { final String[] columnNames = { "Trace File", "States", "Burn-In" }; public int getColumnCount() { return columnNames.length; } public int getRowCount() { int n = traceLists.size(); if (n == 0 || combinedTraces != null) n++; return n; } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { TraceList traceList; if (traceLists.size() == 0) { switch (col) { case 0: return "No files loaded"; case 1: return ""; case 2: return ""; } } else if (row == traceLists.size()) { traceList = combinedTraces; switch (col) { case 0: return traceList.getName(); case 1: return traceList.getMaxState(); case 2: return "-"; } } else { traceList = traceLists.get(row); switch (col) { case 0: return traceList.getName(); case 1: return traceList.getMaxState(); case 2: return traceList.getBurnIn(); } } return null; } public void setValueAt(Object value, int row, int col) { if (col == 2) { setBurnIn(row, (Long) value); } } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } public boolean isCellEditable(int row, int col) { return col == 2 && row < traceLists.size(); } public String getToolTipText(int row, int col) { if (traceLists.size() == 0) { return null; } else if (row == traceLists.size()) { return "Combined trace files"; } else { return traceLists.get(row).getFullName(); } } } class StatisticTableModel extends AbstractTableModel { final String[] columnNames = { "Statistic", "Mean", "ESS", "Type" }; private final DecimalFormat formatter = new DecimalFormat("0.###E0"); private final DecimalFormat formatter2 = new DecimalFormat("####0.###"); private int firstVisibleRow = 0; private int lastVisibleRow = 0; public int getColumnCount() { return columnNames.length; } public int getRowCount() { if (currentTraceLists.size() == 0 || currentTraceLists.get(0) == null) return 0; return commonTraceNames.size(); } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { String traceName = commonTraceNames.get(row); if (col == 0) { return traceName; } if (!homogenousTraceFiles) { return "n/a"; } TraceCorrelation td = currentTraceLists.get(0).getCorrelationStatistics(row); if (td == null) return "-"; if (col == 3) { if (td.isConstant()) { return "*"; } return td.getTraceType().getBrief(); } double value = 0.0; boolean warning = false; boolean extremeWarning = false; switch (col) { case 1: if (td.getTraceType().isCategorical()) return "n/a"; value = td.getMean(); break; case 2: // if (!td.minEqualToMax()) return "-"; value = td.getESS(); if (Double.isNaN(value) || value < 1 || td.isConstant()) { // assume not applicable; should be tested in the computation return "-"; } if (value < 200.0) warning = true; if (value < 100.0) extremeWarning = true; value = Math.round(value); break; } String string; if (Math.abs(value) < 0.1 || Math.abs(value) >= 100000.0) { string = formatter.format(value); } else string = formatter2.format(value); if (warning) { return "<html><font color=\"" + (extremeWarning ? "#EE0000" : "#EEAA00") + "\">" + string + "</font></html> "; } return string; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columnIndex == 0 && currentTraceLists.size() == 1) { //TODO store parameter names in a single object //parameter names are stored both in currentTraceLists and in commonTraceNames //this makes for difficult to maintain code (code below fixes issue #101) currentTraceLists.get(0).getTrace(rowIndex).setName(aValue.toString()); statisticTableModel.fireTableDataChanged(); commonTraceNames.remove(rowIndex); commonTraceNames.add(rowIndex, aValue.toString()); //suggest to select the row of which the name has been changed statisticTable.setRowSelectionInterval(rowIndex, rowIndex); } } @Override public boolean isCellEditable(int row, int col) { return col == 0 && currentTraceLists.size() == 1; } public Class getColumnClass(int c) { if (getRowCount() == 0) { return Object.class; } return getValueAt(0, c).getClass(); } public void setFirstVisibleRow(int row) { firstVisibleRow = row; } public void setLastVisibleRow(int row) { lastVisibleRow = row; } public int getFirstVisibleRow() { return firstVisibleRow; } public int getLastVisibleRow() { return lastVisibleRow; } } public Action getReloadAction() { return reloadAction; } // public Action getExportFullStatisticsAction() { // return exportFullStatisticsAction; // } public Action getExportRawDataAction() { return exportRawDataAction; } public Action getExportDataTableAction() { return exportDataTableAction; } public Action getExportPDFAction() { return exportPDFAction; } public Action getRemoveTraceAction() { return removeTraceAction; } public Action getDemographicAction() { return demographicAction; } public Action getBayesianSkylineAction() { return bayesianSkylineAction; } public Action getExtendedBayesianSkylineAction() { return extendedBayesianSkylineAction; } public Action getSkyGridAction() { return skyGridAction; } public Action getGMRFSkyrideAction() { return gmrfSkyrideAction; } public Action getLineagesThroughTimeAction() { return lineagesThroughTimeAction; } public Action getTraitThroughTimeAction() { return traitThroughTimeAction; } public Action getCreateTemporalAnalysisAction() { return createTemporalAnalysisAction; } public Action getAddDemographicAction() { return addDemographicAction; } public Action getAddBayesianSkylineAction() { return addBayesianSkylineAction; } public Action getAddExtendedBayesianSkylineAction() { return addExtendedBayesianSkylineAction; } public Action getAddTimeDensityAction() { return addTimeDensity; } public Action getConditionalPosteriorDistAction() { return getConditionalPostDistAction; } private final AbstractAction demographicAction = new AbstractAction( AnalysisMenuFactory.DEMOGRAPHIC_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doDemographic(false); } }; private final AbstractAction bayesianSkylineAction = new AbstractAction( AnalysisMenuFactory.BAYESIAN_SKYLINE_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doBayesianSkyline(false); } }; private final AbstractAction extendedBayesianSkylineAction = new AbstractAction( AnalysisMenuFactory.EXTENDED_BAYESIAN_SKYLINE_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doExtendedBayesianSkyline(false); } }; private final AbstractAction skyGridAction = new AbstractAction(AnalysisMenuFactory.SKY_GRID_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doSkyGrid(false); } }; private final AbstractAction gmrfSkyrideAction = new AbstractAction( AnalysisMenuFactory.GMRF_SKYRIDE_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doGMRFSkyride(false); } }; private final AbstractAction lineagesThroughTimeAction = new AbstractAction( AnalysisMenuFactory.LINEAGES_THROUGH_TIME) { public void actionPerformed(ActionEvent ae) { doLineagesThroughTime(false); } }; private final AbstractAction traitThroughTimeAction = new AbstractAction( AnalysisMenuFactory.TRAIT_THROUGH_TIME) { public void actionPerformed(ActionEvent ae) { doTraitThroughTime(false); } }; private final AbstractAction createTemporalAnalysisAction = new AbstractAction( AnalysisMenuFactory.CREATE_TEMPORAL_ANALYSIS) { public void actionPerformed(ActionEvent ae) { doCreateTemporalAnalysis(); } }; private final AbstractAction addDemographicAction = new AbstractAction( AnalysisMenuFactory.ADD_DEMOGRAPHIC_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doDemographic(true); } }; private final AbstractAction addBayesianSkylineAction = new AbstractAction( AnalysisMenuFactory.ADD_BAYESIAN_SKYLINE_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doBayesianSkyline(true); } }; private final AbstractAction addExtendedBayesianSkylineAction = new AbstractAction( AnalysisMenuFactory.ADD_EXTENDED_BAYESIAN_SKYLINE_RECONSTRUCTION) { public void actionPerformed(ActionEvent ae) { doExtendedBayesianSkyline(true); } }; private final AbstractAction addTimeDensity = new AbstractAction(AnalysisMenuFactory.ADD_TIME_DENSITY) { public void actionPerformed(ActionEvent ae) { doAddTimeDensity(); } }; private final AbstractAction getConditionalPostDistAction = new AbstractAction( AnalysisMenuFactory.CONDITIONAL_POST_DIST) { public void actionPerformed(ActionEvent ae) { doFindConditionalPosteriorDistributions(); } }; private final AbstractAction removeTraceAction = new AbstractAction() { public void actionPerformed(ActionEvent ae) { removeTraceList(); } }; private final AbstractAction reloadAction = new AbstractAction("Reload Trace File(s)...") { public void actionPerformed(ActionEvent ae) { refreshTraceList(); } }; // private final AbstractAction exportFullStatisticsAction = new AbstractAction("Export Statistic Summary...") { // public void actionPerformed(ActionEvent ae) { // doExportStatisticSummary(); // } // }; private final AbstractAction exportRawDataAction = new AbstractAction("Export Raw Data...") { public void actionPerformed(ActionEvent ae) { doExportData(true); } }; private final AbstractAction exportDataTableAction = new AbstractAction("Export Data Table...") { public void actionPerformed(ActionEvent ae) { doExportData(false); } }; private final AbstractAction exportPDFAction = new AbstractAction("Export PDF...") { public void actionPerformed(ActionEvent ae) { doExportPDF(); } }; }