/*
* TimeDensityDialog.java
*
* Copyright (C) 2002-2009 Alexei Drummond and Andrew Rambaut
*
* 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 dr.app.tracer.analysis;
import dr.app.gui.components.RealNumberField;
import dr.app.gui.util.LongTask;
import dr.inference.trace.TraceList;
import dr.stats.Variate;
import dr.util.FrequencyDistribution;
import jam.panels.OptionsPanel;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class TimeDensityDialog {
private JFrame frame;
private JComboBox traceCombo;
private String timeTrace = "None selected";
private RealNumberField ageOfYoungestField = new RealNumberField();
private OptionsPanel optionPanel;
public TimeDensityDialog(JFrame frame) {
this.frame = frame;
traceCombo = new JComboBox();
ageOfYoungestField.setValue(0.0);
ageOfYoungestField.setColumns(12);
optionPanel = new OptionsPanel(12, 12);
}
private int findArgument(JComboBox comboBox, String argument) {
for (int i = 0; i < comboBox.getItemCount(); i++) {
String item = ((String) comboBox.getItemAt(i)).toLowerCase();
if (item.indexOf(argument) != -1) return i;
}
return -1;
}
public int showDialog(TraceList traceList, TemporalAnalysisFrame temporalAnalysisFrame) {
setArguments();
for (int j = 0; j < traceList.getTraceCount(); j++) {
String statistic = traceList.getTraceName(j);
traceCombo.addItem(statistic);
}
int index = findArgument(traceCombo, timeTrace);
if (index == -1) index = findArgument(traceCombo, "root");
if (index == -1) index = findArgument(traceCombo, "height");
if (index == -1) index = findArgument(traceCombo, "time");
if (index == -1) index = 0;
traceCombo.setSelectedIndex(index);
final JOptionPane optionPane = new JOptionPane(optionPanel,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null,
null,
null);
optionPane.setBorder(new EmptyBorder(12, 12, 12, 12));
final JDialog dialog = optionPane.createDialog(frame, "Time Density Analysis");
dialog.pack();
int result = JOptionPane.CANCEL_OPTION;
dialog.setVisible(true);
Integer value = (Integer) optionPane.getValue();
if (value != null && value != -1) {
result = value;
}
return result;
}
private void setArguments() {
optionPanel.removeAll();
optionPanel.addComponentWithLabel("Select the trace:", traceCombo);
optionPanel.addSeparator();
optionPanel.addComponentWithLabel("Age of youngest tip:", ageOfYoungestField);
JLabel label3 = new JLabel(
"<html>You can set the age of sampling of the most recent tip in<br>" +
"the tree. If this is set to zero then the plot is shown going<br>" +
"backwards in time, otherwise forwards in time.</html>");
label3.setFont(label3.getFont().deriveFont(((float) label3.getFont().getSize() - 2)));
optionPanel.addSpanningComponent(label3);
}
Timer timer = null;
public void addToTemporalAnalysis(TraceList traceList, TemporalAnalysisFrame frame) {
final AnalyseTimeDensityTask analyseTask = new AnalyseTimeDensityTask(traceList, frame);
final ProgressMonitor progressMonitor = new ProgressMonitor(frame,
"Analysing Time-Density",
"", 0, analyseTask.getLengthOfTask());
progressMonitor.setMillisToPopup(0);
progressMonitor.setMillisToDecideToPopup(0);
timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
progressMonitor.setProgress(analyseTask.getCurrent());
if (progressMonitor.isCanceled() || analyseTask.done()) {
progressMonitor.close();
analyseTask.stop();
timer.stop();
}
}
});
analyseTask.go();
timer.start();
}
class AnalyseTimeDensityTask extends LongTask {
TraceList traceList;
TemporalAnalysisFrame frame;
double ageOfYoungest;
int binCount;
double minTime;
double maxTime;
int stateCount;
private int lengthOfTask = 0;
private int current = 0;
public AnalyseTimeDensityTask(TraceList traceList, TemporalAnalysisFrame frame) {
this.traceList = traceList;
this.frame = frame;
this.binCount = frame.getBinCount();
lengthOfTask = traceList.getStateCount() + binCount;
ageOfYoungest = ageOfYoungestField.getValue();
stateCount = traceList.getStateCount();
}
public int getCurrent() {
return current;
}
public int getLengthOfTask() {
return lengthOfTask;
}
public String getDescription() {
return "Calculating Density...";
}
public String getMessage() {
return null;
}
public Object doWork() {
List<Double> times = traceList.getValues(traceList.getTraceIndex((String) traceCombo.getSelectedItem()));
minTime = frame.getMinTime();
maxTime = frame.getMaxTime();
double delta = (maxTime - minTime) / (binCount - 1);
FrequencyDistribution frequency = new FrequencyDistribution(minTime, binCount, delta);
for (int i = 0; i < times.size(); i++) {
frequency.addValue(getTime(times.get(i)));
}
Variate.D xData = new Variate.D();
Variate.D yData = new Variate.D();
double x = frequency.getLowerBound() - frequency.getBinSize();
xData.add(x + (frequency.getBinSize() / 2.0));
yData.add(0.0);
x += frequency.getBinSize();
for (int i = 0; i < frequency.getBinCount(); i++) {
xData.add(x + (frequency.getBinSize() / 2.0));
double density = frequency.getFrequency(i) / frequency.getBinSize() / times.size();
yData.add(density);
x += frequency.getBinSize();
}
xData.add(x + (frequency.getBinSize() / 2.0));
yData.add(0.0);
frame.addDensity("Density: " + traceList.getName(), xData, yData);
return null;
}
private double getTime(double height) {
if (ageOfYoungest > 0.0) {
return ageOfYoungest - height;
} else {
return ageOfYoungest;
}
}
}
}