package gui; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.ScrollPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.BoxLayout; import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.SwingWorker; import javax.swing.border.TitledBorder; import readers.LogFileReader; import templates.MapBackground; import templates.RateIndicatorBFToKML; import templates.RateIndicatorBFToProcessing; import utils.Utils; import app.SpreadApp; import colorpicker.swing.ColorPicker; @SuppressWarnings("serial") public class RateIndicatorBFTab extends JPanel { // Shared Frame private SpreadApp frame; // Sizing constants private final int leftPanelWidth = 260; private final int leftPanelHeight = 1000; private final int spinningPanelHeight = 20; private final int mapImageWidth = MapBackground.MAP_IMAGE_WIDTH; private final int mapImageHeight = MapBackground.MAP_IMAGE_HEIGHT; private final Dimension minimumDimension = new Dimension(0, 0); // Colors private Color backgroundColor; private Color branchesMaxColor; private Color branchesMinColor; // Locations & coordinates table private InteractiveTableModel table = null; // Strings for paths private String logFilename = null; private File workingDirectory = null; // Text fields private JTextField numberOfIntervalsParser; private JTextField maxAltMappingParser; private JTextField bfCutoffParser; private JTextField kmlPathParser; // Buttons private JButton openLog; private JButton openLocations; private JButton generateKml; private JButton generateProcessing; private JButton saveProcessingPlot; private JButton branchesMaxColorChooser; private JButton branchesMinColorChooser; // Sliders private JSlider burnInParser; private JSlider branchesWidthParser; // Combo boxes private JComboBox meanPoissonPriorParser; private JComboBox poissonPriorOffsetParser; private JComboBox indicatorNameBox; // Left tools pane private JPanel leftPanel; private JPanel tmpPanel; private SpinningPanel sp; private JPanel tmpPanelsHolder; // Processing pane private RateIndicatorBFToProcessing rateIndicatorBFToProcessing; // Progress bar private JProgressBar progressBar; public RateIndicatorBFTab(SpreadApp spreadApp) { this.frame = spreadApp; // Setup miscallenous setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); backgroundColor = new Color(231, 237, 246); branchesMaxColor = new Color(255, 5, 50, 255); branchesMinColor = new Color(0, 0, 0, 255); GridBagConstraints c = new GridBagConstraints(); // Setup text fields numberOfIntervalsParser = new JTextField("100", 10); maxAltMappingParser = new JTextField("500000", 10); bfCutoffParser = new JTextField("3.0", 5); kmlPathParser = new JTextField("output.kml", 10); // Setup buttons openLog = new JButton("Open", SpreadApp.logIcon); openLocations = new JButton("Open", SpreadApp.locationsIcon); generateKml = new JButton("Generate", SpreadApp.nuclearIcon); generateProcessing = new JButton("Plot", SpreadApp.processingIcon); saveProcessingPlot = new JButton("Save", SpreadApp.saveIcon); branchesMaxColorChooser = new JButton("Setup max"); branchesMinColorChooser = new JButton("Setup min"); // Setup sliders burnInParser = new JSlider(JSlider.HORIZONTAL, 0, 100, 10); burnInParser.setMajorTickSpacing(20); burnInParser.setMinorTickSpacing(10); burnInParser.setPaintTicks(true); burnInParser.setPaintLabels(true); branchesWidthParser = new JSlider(JSlider.HORIZONTAL, 2, 10, 4); branchesWidthParser.setMajorTickSpacing(2); branchesWidthParser.setMinorTickSpacing(1); branchesWidthParser.setPaintTicks(true); branchesWidthParser.setPaintLabels(true); // Setup Combo boxes indicatorNameBox = new JComboBox(new String[] {"indicator"}); // Setup progress bar progressBar = new JProgressBar(); /** * left tools pane * */ leftPanel = new JPanel(); leftPanel.setBackground(backgroundColor); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); // leftPanel.setSize(new Dimension(leftPanelWidth, leftPanelHeight)); // Listeners openLog.addActionListener(new ListenOpenLog()); generateKml.addActionListener(new ListenGenerateKml()); openLocations .addActionListener(new ListenOpenLocationCoordinatesEditor()); generateProcessing.addActionListener(new ListenGenerateProcessing()); saveProcessingPlot.addActionListener(new ListenSaveProcessingPlot()); branchesMaxColorChooser .addActionListener(new ListenBranchesMaxColorChooser()); branchesMinColorChooser .addActionListener(new ListenBranchesMinColorChooser()); // ///////////// // ---INPUT---// // ///////////// tmpPanelsHolder = new JPanel(); tmpPanelsHolder.setLayout(new BoxLayout(tmpPanelsHolder, BoxLayout.Y_AXIS)); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Load log file:")); tmpPanel.add(openLog); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Setup location coordinates:")); tmpPanel.add(openLocations); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Indicator attribute name:")); tmpPanel.add(indicatorNameBox); tmpPanelsHolder.add(tmpPanel); sp = new SpinningPanel(tmpPanelsHolder, " Input", new Dimension( leftPanelWidth, spinningPanelHeight)); sp.showBottom(true); leftPanel.add(sp); // //////////////////// // ---COMPUTATIONS---// // //////////////////// tmpPanelsHolder = new JPanel(); tmpPanelsHolder.setLayout(new BoxLayout(tmpPanelsHolder, BoxLayout.Y_AXIS)); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Specify burn-in %:")); tmpPanel.add(burnInParser); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setLayout(new GridBagLayout()); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Poisson prior mean / offset:")); String[] meanPoissonPrior = { "log(2)", " " }; meanPoissonPriorParser = new JComboBox(meanPoissonPrior); meanPoissonPriorParser.setEditable(true); meanPoissonPriorParser.setPreferredSize(new Dimension(70, 25)); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; tmpPanel.add(meanPoissonPriorParser, c); String[] poissonPriorOffset = { "n-1", " " }; poissonPriorOffsetParser = new JComboBox(poissonPriorOffset); poissonPriorOffsetParser.setEditable(true); poissonPriorOffsetParser.setPreferredSize(new Dimension(70, 25)); c.gridx = 2; c.gridy = 0; tmpPanel.add(poissonPriorOffsetParser, c); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Bayes Factor cut-off:")); tmpPanel.add(bfCutoffParser); tmpPanelsHolder.add(tmpPanel); sp = new SpinningPanel(tmpPanelsHolder, " Computations", new Dimension(leftPanelWidth, spinningPanelHeight)); sp.showBottom(false); leftPanel.add(sp); // //////////////////////// // ---BRANCHES MAPPING---// // //////////////////////// tmpPanelsHolder = new JPanel(); tmpPanelsHolder.setLayout(new BoxLayout(tmpPanelsHolder, BoxLayout.Y_AXIS)); // Rates color mapping: tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setLayout(new GridBagLayout()); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Rates color mapping:")); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; tmpPanel.add(branchesMinColorChooser, c); c.gridx = 2; c.gridy = 0; tmpPanel.add(branchesMaxColorChooser, c); tmpPanelsHolder.add(tmpPanel); // Branches width: tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Rates width:")); tmpPanel.add(branchesWidthParser); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Number of intervals:")); tmpPanel.add(numberOfIntervalsParser); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Maximal altitude:")); tmpPanel.add(maxAltMappingParser); tmpPanelsHolder.add(tmpPanel); sp = new SpinningPanel(tmpPanelsHolder, " Branches mapping", new Dimension(leftPanelWidth, spinningPanelHeight)); sp.showBottom(false); leftPanel.add(sp); // ////////////// // ---OUTPUT---// // ////////////// tmpPanelsHolder = new JPanel(); tmpPanelsHolder.setLayout(new BoxLayout(tmpPanelsHolder, BoxLayout.Y_AXIS)); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("KML name:")); tmpPanel.add(kmlPathParser); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setLayout(new GridBagLayout()); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Generate KML / Plot map:")); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; tmpPanel.add(generateKml, c); c.gridx = 2; c.gridy = 0; tmpPanel.add(generateProcessing, c); c.ipady = 7; c.gridwidth = 3; c.gridx = 0; c.gridy = 1; tmpPanel.add(progressBar, c); tmpPanelsHolder.add(tmpPanel); tmpPanel = new JPanel(); tmpPanel.setMaximumSize(new Dimension(leftPanelWidth, 100)); tmpPanel.setBackground(backgroundColor); tmpPanel.setBorder(new TitledBorder("Save plot:")); tmpPanel.add(saveProcessingPlot); tmpPanelsHolder.add(tmpPanel); sp = new SpinningPanel(tmpPanelsHolder, " Output", new Dimension( leftPanelWidth, spinningPanelHeight)); sp.showBottom(false); leftPanel.add(sp); // //////////////////////// // ---LEFT SCROLL PANE---// // //////////////////////// JScrollPane leftScrollPane = new JScrollPane(leftPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); leftScrollPane.setMinimumSize(minimumDimension); leftScrollPane.setMaximumSize(new Dimension(leftPanelWidth, leftPanelHeight)); /** * Processing pane * */ rateIndicatorBFToProcessing = new RateIndicatorBFToProcessing(); rateIndicatorBFToProcessing.setPreferredSize(new Dimension( mapImageWidth, mapImageHeight)); // if (System.getProperty("java.runtime.name").toLowerCase().startsWith( // "openjdk")) { // // JScrollPane rightScrollPane = new JScrollPane( // rateIndicatorBFToProcessing, // JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, // JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // rightScrollPane.setMinimumSize(minimumDimension); // // SplitPane splitPane = new SplitPane(JSplitPane.HORIZONTAL_SPLIT, // leftScrollPane, rightScrollPane); // splitPane.setDividerLocation(leftPanelWidth); // // this.add(splitPane); // // } else { ScrollPane rightScrollPane = new ScrollPane( ScrollPane.SCROLLBARS_ALWAYS); rightScrollPane.add(rateIndicatorBFToProcessing); rightScrollPane.setMinimumSize(minimumDimension); SplitPane splitPane = new SplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScrollPane, rightScrollPane); splitPane.setDividerLocation(leftPanelWidth); this.add(splitPane); // } }// END: Constructor private void populateInidcatorCombobox() { LogFileReader parser = new LogFileReader(); String [] colNames = parser.getColNames(logFilename); // remove numbers from end of column name, and count their occurrances Map<String, Integer> map = new HashMap<String, Integer>(); for (String colName : colNames) { colName = colName.replaceAll("[0-9]*$", ""); if (map.containsKey(colName)) { map.put(colName, map.get(colName) + 1); } else { map.put(colName, 1); } } // make those that occur more than once a candidate List<String> indicatorNames = new ArrayList<String>(); for (String colName : map.keySet()) { if (map.get(colName) > 1) { indicatorNames.add(colName); } } // re-initialise combobox ComboBoxModel model = new DefaultComboBoxModel(indicatorNames.toArray(new String[0])); indicatorNameBox.setModel(model); } private class ListenOpenLog implements ActionListener { public void actionPerformed(ActionEvent ev) { try { String[] logFiles = new String[] { "log" }; final JFileChooser chooser = new JFileChooser(); chooser.setDialogTitle("Loading tree file..."); chooser.setMultiSelectionEnabled(false); chooser.addChoosableFileFilter(new SimpleFileFilter(logFiles, "Log files (*.log)")); chooser.setCurrentDirectory(workingDirectory); int returnVal = chooser.showOpenDialog(Utils.getActiveFrame()); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); logFilename = file.getAbsolutePath(); System.out.println("Opened " + logFilename + "\n"); File tmpDir = chooser.getCurrentDirectory(); if (tmpDir != null) { workingDirectory = tmpDir; } populateInidcatorCombobox(); } else { System.out.println("Could not Open! \n"); } } catch (Exception e) { Utils.handleException(e, e.getMessage()); }// END: try-catch block }// END: actionPerformed }// END: ListenOpenLog private class ListenOpenLocationCoordinatesEditor implements ActionListener { public void actionPerformed(ActionEvent ev) { try { LocationCoordinatesEditor locationCoordinatesEditor = new LocationCoordinatesEditor(frame); locationCoordinatesEditor.launch(workingDirectory); table = locationCoordinatesEditor.getTable(); } catch (Exception e) { Utils.handleException(e, e.getMessage()); } } }// END: ListenOpenLocations private class ListenBranchesMinColorChooser implements ActionListener { public void actionPerformed(ActionEvent ev) { Color c = ColorPicker.showDialog(Utils.getActiveFrame(), "Choose minimum branches color...", branchesMinColor, true); if (c != null) branchesMinColor = c; } } private class ListenBranchesMaxColorChooser implements ActionListener { public void actionPerformed(ActionEvent ev) { Color c = ColorPicker.showDialog(Utils.getActiveFrame(), "Choose maximum branches color...", branchesMaxColor, true); if (c != null) branchesMaxColor = c; } } private class ListenGenerateKml implements ActionListener { public void actionPerformed(ActionEvent ev) { if (logFilename == null) { new ListenOpenLog().actionPerformed(ev); } else if (table == null) { new ListenOpenLocationCoordinatesEditor().actionPerformed(ev); } else { generateKml.setEnabled(false); progressBar.setIndeterminate(true); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { // Executed in background thread public Void doInBackground() { try { RateIndicatorBFToKML rateIndicatorBFToKML = new RateIndicatorBFToKML(); rateIndicatorBFToKML.setTable(table); rateIndicatorBFToKML.setLogFileParser(logFilename, burnInParser.getValue() / 100.0, indicatorNameBox.getSelectedItem().toString()); rateIndicatorBFToKML.setBfCutoff(Double .valueOf(bfCutoffParser.getText())); rateIndicatorBFToKML.setMaxAltitudeMapping(Double .valueOf(maxAltMappingParser.getText())); rateIndicatorBFToKML .setNumberOfIntervals(Integer .valueOf(numberOfIntervalsParser .getText())); rateIndicatorBFToKML .setKmlWriterPath(workingDirectory .toString().concat("/").concat( kmlPathParser.getText())); rateIndicatorBFToKML .setMinBranchRedMapping(branchesMinColor .getRed()); rateIndicatorBFToKML .setMinBranchGreenMapping(branchesMinColor .getGreen()); rateIndicatorBFToKML .setMinBranchBlueMapping(branchesMinColor .getBlue()); rateIndicatorBFToKML .setMinBranchOpacityMapping(branchesMinColor .getAlpha()); rateIndicatorBFToKML .setMaxBranchRedMapping(branchesMaxColor .getRed()); rateIndicatorBFToKML .setMaxBranchGreenMapping(branchesMaxColor .getGreen()); rateIndicatorBFToKML .setMaxBranchBlueMapping(branchesMaxColor .getBlue()); rateIndicatorBFToKML .setMaxBranchOpacityMapping(branchesMaxColor .getAlpha()); rateIndicatorBFToKML .setBranchWidth(branchesWidthParser .getValue()); if (meanPoissonPriorParser.getSelectedIndex() == 0) { rateIndicatorBFToKML .setDefaultMeanPoissonPrior(); } else { rateIndicatorBFToKML .setUserMeanPoissonPrior(Double .valueOf(meanPoissonPriorParser .getSelectedItem() .toString())); } if (poissonPriorOffsetParser.getSelectedIndex() == 0) { rateIndicatorBFToKML .setDefaultPoissonPriorOffset(); } else { rateIndicatorBFToKML .setUserPoissonPriorOffset(Double .valueOf(poissonPriorOffsetParser .getSelectedItem() .toString())); } rateIndicatorBFToKML.GenerateKML(); System.out.println("Finished in: " + RateIndicatorBFToKML.time + " msec \n"); } catch (final OutOfMemoryError e) { Utils.handleException(e, "Increase Java Heap Space"); // SwingUtilities.invokeLater(new Runnable() { // // public void run() { // // e.printStackTrace(); // // String msg = String.format( // "Unexpected problem: %s", e // .toString()); // // JOptionPane.showMessageDialog(Utils // .getActiveFrame(), msg // + "\nIncrease Java Heap Space", // "Error", JOptionPane.ERROR_MESSAGE, // SpreadApp.errorIcon); // // } // }); } catch (Exception e) { Utils.handleException(e, null); } return null; }// END: doInBackground() // Executed in event dispatch thread public void done() { generateKml.setEnabled(true); progressBar.setIndeterminate(false); System.out.println("Generated " + workingDirectory.toString().concat("/") .concat(kmlPathParser.getText())); } }; worker.execute(); }// END: if not loaded }// END: actionPerformed }// END: ListenGenerateKml private class ListenGenerateProcessing implements ActionListener { public void actionPerformed(ActionEvent ev) { if (logFilename == null) { new ListenOpenLog().actionPerformed(ev); } else if (table == null) { new ListenOpenLocationCoordinatesEditor().actionPerformed(ev); } else { generateProcessing.setEnabled(false); progressBar.setIndeterminate(true); SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { // Executed in background thread public Void doInBackground() { try { rateIndicatorBFToProcessing.setTable(table); rateIndicatorBFToProcessing.setLogFilePath( logFilename, burnInParser.getValue() / 100.0, indicatorNameBox.getSelectedItem().toString()); rateIndicatorBFToProcessing.setBfCutoff(Double .valueOf(bfCutoffParser.getText())); // rateIndicatorBFToProcessing // .setNumberOfIntervals(Integer // .valueOf(numberOfIntervalsParser // .getText())); rateIndicatorBFToProcessing .setMinBranchRedMapping(branchesMinColor .getRed()); rateIndicatorBFToProcessing .setMinBranchGreenMapping(branchesMinColor .getGreen()); rateIndicatorBFToProcessing .setMinBranchBlueMapping(branchesMinColor .getBlue()); rateIndicatorBFToProcessing .setMinBranchOpacityMapping(branchesMinColor .getAlpha()); rateIndicatorBFToProcessing .setMaxBranchRedMapping(branchesMaxColor .getRed()); rateIndicatorBFToProcessing .setMaxBranchGreenMapping(branchesMaxColor .getGreen()); rateIndicatorBFToProcessing .setMaxBranchBlueMapping(branchesMaxColor .getBlue()); rateIndicatorBFToProcessing .setMaxBranchOpacityMapping(branchesMaxColor .getAlpha()); rateIndicatorBFToProcessing .setBranchWidth(branchesWidthParser .getValue() / 2); if (meanPoissonPriorParser.getSelectedIndex() == 0) { rateIndicatorBFToProcessing .setDefaultMeanPoissonPrior(); } else { rateIndicatorBFToProcessing .setUserMeanPoissonPrior(Double .valueOf(meanPoissonPriorParser .getSelectedItem() .toString())); } if (poissonPriorOffsetParser.getSelectedIndex() == 0) { rateIndicatorBFToProcessing .setDefaultPoissonPriorOffset(); } else { rateIndicatorBFToProcessing .setUserPoissonPriorOffset(Double .valueOf(poissonPriorOffsetParser .getSelectedItem() .toString())); } rateIndicatorBFToProcessing.init(); } catch (final Exception e) { Utils.handleException(e, null); } return null; }// END: doInBackground() // Executed in event dispatch thread public void done() { generateProcessing.setEnabled(true); progressBar.setIndeterminate(false); frame.setStatus("Finished. \n"); } }; worker.execute(); }// END: if not loaded }// END: actionPerformed }// END: ListenGenerateProcessing private class ListenSaveProcessingPlot implements ActionListener { public void actionPerformed(ActionEvent ev) { try { JFileChooser chooser = new JFileChooser(); chooser.setDialogTitle("Saving as png file..."); int returnVal = chooser.showSaveDialog(Utils.getActiveFrame()); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); String filename = file.getAbsolutePath(); rateIndicatorBFToProcessing.save(filename); frame.setStatus("Saved " + filename + "\n"); } else { frame.setStatus("Could not Save! \n"); } } catch (Exception e) { Utils.handleException(e, e.getMessage()); }// END: try-catch block }// END: actionPerformed }// END: ListenSaveProcessingPlot }// END: class