/*
* Copyright (c) 2007-2011 by The Broad Institute of MIT and Harvard. All Rights Reserved.
*
* This software is licensed under the terms of the GNU Lesser General Public License (LGPL),
* Version 2.1 which is available at http://www.opensource.org/licenses/lgpl-2.1.php.
*
* THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR
* WARRANTES OF ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, WHETHER
* OR NOT DISCOVERABLE. IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR RESPECTIVE
* TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES
* OF ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
* ECONOMIC DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER
* THE BROAD OR MIT SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT
* SHALL KNOW OF THE POSSIBILITY OF THE FOREGOING.
*/
/*
* Created by JFormDesigner on Sat Dec 04 19:26:01 EST 2010
*/
package org.broad.igv.util.stats;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.*;
import org.broad.igv.track.AttributeManager;
import org.broad.igv.track.Track;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYStepRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* @author jrobinso
*/
public class KMPlotFrame extends JFrame {
Collection<Track> tracks;
private XYPlot plot;
// TODO -- control to set this
int maxTime = 60;
public KMPlotFrame(Collection<Track> tracks) {
//setLocationRelativeTo(owner);
this.tracks = tracks;
initComponents();
XYDataset dataset = updateDataset();
JFreeChart chart = ChartFactory.createXYLineChart(
"",
"Time",
"Survival",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false);
XYStepRenderer renderer = new XYStepRenderer();
plot = chart.getXYPlot();
plot.setRenderer(renderer);
ChartPanel plotPanel = new ChartPanel(chart);
contentPanel.add(plotPanel, BorderLayout.CENTER);
censurColumnControl.addItem("");
//sampleColumnControl.addItem("");
survivalColumnControl.addItem("");
groupByControl.addItem("");
final List<String> allAttributes = AttributeManager.getInstance().getAttributeNames();
final List<String> groupableAttributes = AttributeManager.getInstance().getGroupableAttributes();
// Populate pulldowns, and make guesses for column names.
String survivalColumn = null;
String censureColumn = null;
String sampleColumn = null;
for (String key : allAttributes) {
censurColumnControl.addItem(key);
//sampleColumnControl.addItem(key);
survivalColumnControl.addItem(key);
String tmp = key.toLowerCase();
if (tmp.contains("survival") || tmp.contains("daystodeath")) survivalColumn = key;
if (tmp.contains("censure")) censureColumn = key;
if (tmp.contains("sample")) sampleColumn = key;
}
for (String key : groupableAttributes) {
groupByControl.addItem(key);
}
if (survivalColumn != null) {
survivalColumnControl.setSelectedItem(survivalColumn);
}
if (censureColumn != null) {
censurColumnControl.setSelectedItem(censureColumn);
}
if (sampleColumn != null) {
//sampleColumnControl.setSelectedItem(sampleColumn);
}
}
private void closeButtonActionPerformed(ActionEvent e) {
setVisible(false);
}
public XYDataset updateDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
final String survivalColumn = (String) survivalColumnControl.getSelectedItem();
final String censureColumn = (String) censurColumnControl.getSelectedItem();
final String groupByColumn = (String) groupByControl.getSelectedItem();
if (survivalColumn != null) {
ArrayList<DataPoint> dataPoints = new ArrayList(tracks.size());
HashSet<String> participants = new HashSet();
for (Track t : tracks) {
try {
// Get the participant (sample) attribute value for this track
//final Object selectedItem = sampleColumnControl.getSelectedItem();
//if (selectedItem != null) {
String participant = t.getSample(); // t.getAttributeValue(selectedItem.toString());
if (!participants.contains(participant)) { // Don't add same participant twice.
participants.add(participant);
// Get the survival time.
String survivalString = t.getAttributeValue(survivalColumn);
int survivalDays = Integer.parseInt(survivalString);
int survival = survivalDays;
// Is the patient censured at the end of the survival period?
String censureString = censureColumn == null ? null : t.getAttributeValue(censureColumn);
boolean censured = censureString != null && censureString.equals("1");
String group = groupByColumn == null ? null : t.getAttributeValue(groupByColumn);
if (group == null) group = "<No value>";
dataPoints.add(new DataPoint(participant, survival, censured, group));
} else {
// TODO -- check consistency of participant data
}
// }
} catch (NumberFormatException e) {
// Just skip
}
}
// Segregate by group
Map<String, ArrayList<DataPoint>> map = new HashMap();
for (DataPoint dp : dataPoints) {
String g = dp.getGroup();
ArrayList<DataPoint> pts = map.get(g);
if (pts == null) {
pts = new ArrayList();
map.put(g, pts);
}
pts.add(dp);
}
//XYSeries series1;
for (Map.Entry<String, ArrayList<DataPoint>> entry : map.entrySet()) {
java.util.List<DataPoint> pts = entry.getValue();
Collections.sort(pts);
int[] time = new int[pts.size()];
boolean[] censured = new boolean[pts.size()];
for (int i = 0; i < pts.size(); i++) {
//int months = Math.max(1, pts.get(i).time / 30); // <= TODO -- HARDCODED MONTH DATE
time[i] = pts.get(i).time;
censured[i] = pts.get(i).censured;
}
java.util.List<KaplanMeierEstimator.Interval> controlIntervals = KaplanMeierEstimator.compute(time, censured);
XYSeries series1 = new XYSeries(entry.getKey());
for (KaplanMeierEstimator.Interval interval : controlIntervals) {
series1.add(interval.getEnd(), interval.getCumulativeSurvival());
}
dataset.addSeries(series1);
}
}
return dataset;
}
private void survivalColumnControlActionPerformed(ActionEvent e) {
XYDataset dataset = updateDataset();
plot.setDataset(dataset);
repaint();
}
public static class DataPoint implements Comparable<DataPoint> {
String participant;
int time;
boolean censured;
private String group;
DataPoint(String participant, int time, boolean censured, String group) {
this.censured = censured;
this.participant = participant;
this.group = group;
this.time = time;
}
public int compareTo(DataPoint dataPoint) {
return time - dataPoint.time;
}
public String getGroup() {
return group;
}
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
// Generated using JFormDesigner non-commercial license
dialogPane = new JPanel();
contentPanel = new JPanel();
panel1 = new JPanel();
panel2 = new JPanel();
label2 = new JLabel();
survivalColumnControl = new JComboBox();
panel3 = new JPanel();
label3 = new JLabel();
censurColumnControl = new JComboBox();
panel4 = new JPanel();
label4 = new JLabel();
groupByControl = new JComboBox();
//======== this ========
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Kaplan-Meier Plot");
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
//======== dialogPane ========
{
dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12));
dialogPane.setLayout(new BorderLayout());
//======== contentPanel ========
{
contentPanel.setLayout(new BorderLayout());
//======== panel1 ========
{
panel1.setAlignmentX(0.0F);
panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));
//======== panel2 ========
{
panel2.setAlignmentX(1.0F);
panel2.setLayout(null);
//---- label2 ----
label2.setText("Survival column");
panel2.add(label2);
label2.setBounds(new Rectangle(new Point(5, 10), label2.getPreferredSize()));
//---- survivalColumnControl ----
survivalColumnControl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
survivalColumnControlActionPerformed(e);
}
});
panel2.add(survivalColumnControl);
survivalColumnControl.setBounds(120, 5, 235, survivalColumnControl.getPreferredSize().height);
{ // compute preferred size
Dimension preferredSize = new Dimension();
for(int i = 0; i < panel2.getComponentCount(); i++) {
Rectangle bounds = panel2.getComponent(i).getBounds();
preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
}
Insets insets = panel2.getInsets();
preferredSize.width += insets.right;
preferredSize.height += insets.bottom;
panel2.setMinimumSize(preferredSize);
panel2.setPreferredSize(preferredSize);
}
}
panel1.add(panel2);
//======== panel3 ========
{
panel3.setAlignmentX(1.0F);
panel3.setLayout(null);
//---- label3 ----
label3.setText("Censored column");
panel3.add(label3);
label3.setBounds(new Rectangle(new Point(5, 10), label3.getPreferredSize()));
//---- censurColumnControl ----
censurColumnControl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
survivalColumnControlActionPerformed(e);
}
});
panel3.add(censurColumnControl);
censurColumnControl.setBounds(120, 5, 235, censurColumnControl.getPreferredSize().height);
{ // compute preferred size
Dimension preferredSize = new Dimension();
for(int i = 0; i < panel3.getComponentCount(); i++) {
Rectangle bounds = panel3.getComponent(i).getBounds();
preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
}
Insets insets = panel3.getInsets();
preferredSize.width += insets.right;
preferredSize.height += insets.bottom;
panel3.setMinimumSize(preferredSize);
panel3.setPreferredSize(preferredSize);
}
}
panel1.add(panel3);
//======== panel4 ========
{
panel4.setAlignmentX(1.0F);
panel4.setLayout(null);
//---- label4 ----
label4.setText("Group by");
panel4.add(label4);
label4.setBounds(new Rectangle(new Point(5, 10), label4.getPreferredSize()));
//---- groupByControl ----
groupByControl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
survivalColumnControlActionPerformed(e);
}
});
panel4.add(groupByControl);
groupByControl.setBounds(120, 5, 235, groupByControl.getPreferredSize().height);
{ // compute preferred size
Dimension preferredSize = new Dimension();
for(int i = 0; i < panel4.getComponentCount(); i++) {
Rectangle bounds = panel4.getComponent(i).getBounds();
preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
}
Insets insets = panel4.getInsets();
preferredSize.width += insets.right;
preferredSize.height += insets.bottom;
panel4.setMinimumSize(preferredSize);
panel4.setPreferredSize(preferredSize);
}
}
panel1.add(panel4);
}
contentPanel.add(panel1, BorderLayout.NORTH);
}
dialogPane.add(contentPanel, BorderLayout.CENTER);
}
contentPane.add(dialogPane, BorderLayout.CENTER);
setSize(565, 510);
setLocationRelativeTo(getOwner());
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
// Generated using JFormDesigner non-commercial license
private JPanel dialogPane;
private JPanel contentPanel;
private JPanel panel1;
private JPanel panel2;
private JLabel label2;
private JComboBox survivalColumnControl;
private JPanel panel3;
private JLabel label3;
private JComboBox censurColumnControl;
private JPanel panel4;
private JLabel label4;
private JComboBox groupByControl;
// JFormDesigner - End of variables declaration //GEN-END:variables
}