/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 */
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.biojava.nbio.survival.kaplanmeier.figure;

import org.biojava.nbio.survival.cox.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;

/**
 *
 * @author Scooter Willis <willishf at gmail dot com>
 */
public class KaplanMeierFigure extends JPanel {

	private static final long serialVersionUID = 1L;
	
	ArrayList<String> title = new ArrayList<String>();
    /**
     *
     */
    private int top;
    /**
     *
     */
    private int bottom;
    /**
     *
     */
    private int left;
    private int yaxisLabel = 20;
    /**
     *
     */
    private int right;
    int titleHeight;
    int xAxisLabelHeight;
    int labelWidth;
    double minTime = 0.0;
    double maxTime = 10.0;
    double minPercentage = 0.0;
    double maxPercentage = 1.0;
    FontMetrics fm;
    KMFigureInfo kmfi = new KMFigureInfo();
    LinkedHashMap<String, ArrayList<CensorStatus>> survivalData = new LinkedHashMap<String, ArrayList<CensorStatus>>();
    ArrayList<String> lineInfoList = new ArrayList<String>();
    SurvFitInfo sfi = new SurvFitInfo();
    private String fileName = "";
    private ArrayList<Double> xAxisTimeValues = new ArrayList<Double>();
    private ArrayList<Integer> xAxisTimeCoordinates = new ArrayList<Integer>();

    /**
     *
     */
    public KaplanMeierFigure() {
        super();
        setSize(500, 400);
        setBackground(Color.WHITE);
    }

    /**
     * Get the name of the groups that are being plotted in the figure
     *
     * @return
     */
    public ArrayList<String> getGroups() {
        return new ArrayList<String>(survivalData.keySet());
    }

    /**
     * To get the median percentile for a particular group pass the value of
     * .50.
     *
     * @param group
     * @param percentile
     * @return
     */
    public Double getSurvivalTimePercentile(String group, double percentile) {

        StrataInfo si = sfi.getStrataInfoHashMap().get(group);
        ArrayList<Double> percentage = si.getSurv();
        Integer percentileIndex = null;
        for (int i = 0; i < percentage.size(); i++) {
            if (percentage.get(i) == percentile) {
                if (i + 1 < percentage.size()) {
                    percentileIndex = i + 1;
                }
                break;
            } else if (percentage.get(i) < percentile) {
                percentileIndex = i;
                break;
            }
        }
        if (percentileIndex != null) {
            return si.getTime().get(percentileIndex);
        } else {
            return null;
        }
    }

    /**
     *
     * @param kmfi
     */
    public void setKMFigureInfo(KMFigureInfo kmfi) {
        this.kmfi = kmfi;
        if (kmfi.width != null && kmfi.height != null) {
            this.setSize(kmfi.width, kmfi.height);
        }
    }

    public KMFigureInfo getKMFigureInfo() {
        return kmfi;
    }

    /**
     *
     * @param lineInfoList
     */
    public void setFigureLineInfo(ArrayList<String> lineInfoList) {
        this.lineInfoList = lineInfoList;
        this.repaint();
    }

    /**
     *
     * @param title Title of figures
     * @param ci
     * @param strataVariable The column that based on value will do a figure
     * line
     * @param legendMap Map the value in the column to something readable
     * @param useWeighted
     * @throws Exception
     */
    public void setCoxInfo(ArrayList<String> title, CoxInfo ci, String strataVariable, LinkedHashMap<String, String> legendMap, Boolean useWeighted) throws Exception {
        LinkedHashMap<String, ArrayList<CensorStatus>> survivalData = new LinkedHashMap<String, ArrayList<CensorStatus>>();
        ArrayList<SurvivalInfo> siList = ci.getSurvivalInfoList();
        int n = 0;
        int event = 0;
        for (SurvivalInfo si : siList) {
            String strata = si.getOriginalMetaData(strataVariable);
            String legend = legendMap.get(strata);
            if (legend == null) {

                legend = strata;
            }
            ArrayList<CensorStatus> censorStatusList = survivalData.get(legend);
            if (censorStatusList == null) {
                censorStatusList = new ArrayList<CensorStatus>();
                survivalData.put(legend, censorStatusList);
            }
            CensorStatus cs = new CensorStatus(strata, si.getTime(), si.getStatus() + "");
            cs.weight = si.getWeight();
            censorStatusList.add(cs);
            n++;
            if (si.getStatus() == 1) {
                event++;
            }
        }

        setSurvivalData(title, survivalData, useWeighted);
        CoxCoefficient cc = ci.getCoefficient(strataVariable);
        //DecimalFormat df = new DecimalFormat("#.##");
        String line1 = "HR=" + fmt(cc.getHazardRatio(), 2, 0) + " (CI:" + fmt(cc.getHazardRatioLoCI(), 2, 0) + "-" + fmt(cc.getHazardRatioHiCI(), 2, 0) + ")";
        String line2 = "p=" + fmt(cc.getPvalue(), 3, 0);
       // String line2 = "logrank P=" + fmt(ci.getScoreLogrankTestpvalue(), 3, 0);
        String line3 = "n=" + n + " events=" + event;
//        System.out.println("setCoxInfo=" + cc.pvalue + " " + title);


        ArrayList<String> lines = new ArrayList<String>();
        lines.add(line1);
        lines.add(line2);
        lines.add(line3);
        setFigureLineInfo(lines);
    }

    /**
     *
     * @param d
     * @param precision
     * @param pad
     * @return
     */
    public static String fmt(Double d, int precision, int pad) {
        String value = "";
        DecimalFormat dfe = new DecimalFormat("0.00E0");
        String dpad = "0.";
        double p = 1.0;
        for (int i = 0; i < (precision); i++) {
            dpad = dpad + "0";
            p = p / 10.0;
        }
        DecimalFormat df = new DecimalFormat(dpad);
        if (Math.abs(d) >= p) {
            value = df.format(d);
        } else {
            value = dfe.format(d);
        }
        int length = value.length();
        int extra = pad - length;
        if (extra > 0) {
            for (int i = 0; i < extra; i++) {
                value = " " + value;
            }
        }
        return value;
    }

    /**
     *
     * @return
     */
    public SurvFitInfo getSurvivalFitInfo() {
        return sfi;
    }

    /**
     * Allow setting of points in the figure where weighted correction has been
     * done and percentage has already been calculated.
     *
     * @param title
     * @param sfi
     * @param userSetMaxTime
     */
    public void setSurvivalData(ArrayList<String> title, SurvFitInfo sfi, Double userSetMaxTime) {
        this.title = title;
        LinkedHashMap<String, StrataInfo> strataInfoHashMap = sfi.getStrataInfoHashMap();
        Double mTime = null;
        for (StrataInfo si : strataInfoHashMap.values()) {
            for (double t : si.getTime()) {
                if (mTime == null || t > mTime) {
                    mTime = t;
                }
            }
        }

        int evenCheck = Math.round((float) mTime.floatValue());
        if (evenCheck % 2 == 1) {
            evenCheck = evenCheck + 1;
        }
        this.maxTime = (double) evenCheck;

        if (userSetMaxTime != null && userSetMaxTime > maxTime) {
            this.maxTime = userSetMaxTime;
        }
        this.sfi = sfi;
        if (sfi.getStrataInfoHashMap().size() == 1) {
            return;
        }
        this.repaint();
    }

    /**
     * The data will set the max time which will result in off time points for
     * tick marks
     *
     * @param title
     * @param survivalData
     * @param useWeighted
     * @throws Exception
     */
    public void setSurvivalData(ArrayList<String> title, LinkedHashMap<String, ArrayList<CensorStatus>> survivalData, Boolean useWeighted) throws Exception {
        this.setSurvivalData(title, survivalData, null, useWeighted);
    }

    /**
     *
     * @param title
     * @param survivalData
     * @param userSetMaxTime
     * @param useWeighted
     * @throws Exception
     */
    public void setSurvivalData(ArrayList<String> title, LinkedHashMap<String, ArrayList<CensorStatus>> survivalData, Double userSetMaxTime, Boolean useWeighted) throws Exception {
        this.title = title;
        this.survivalData = survivalData;
        Double mTime = null;
        ArrayList<String> labels = new ArrayList<String>(survivalData.keySet());
        Collections.sort(labels);
        for (String legend : labels) {
            ArrayList<CensorStatus> censorStatusList = survivalData.get(legend);
            for (CensorStatus cs : censorStatusList) {

                if (mTime == null || cs.time > mTime) {
                    mTime = cs.time;
                }
            }
        }

        int evenCheck = Math.round((float) mTime.floatValue());
        if (evenCheck % 2 == 1) {
            evenCheck = evenCheck + 1;
        }
        this.maxTime = (double) evenCheck;

        if (userSetMaxTime != null && userSetMaxTime > maxTime) {
            this.maxTime = userSetMaxTime;
        }

        //calculate percentages
        SurvFitKM survFitKM = new SurvFitKM();
        sfi = survFitKM.process(survivalData, useWeighted);
        this.repaint();
    }

    /**
     * Save data from survival curve to text file
     *
     * @param fileName
     * @throws Exception
     */
    public void saveSurvivalData(String fileName) throws Exception {
        FileWriter fw = new FileWriter(fileName);
        fw.write("index\tTIME\tSTATUS\tGROUP\r\n");
        int index = 0;
        for (String group : survivalData.keySet()) {
            ArrayList<CensorStatus> sd = survivalData.get(group);
            for (CensorStatus cs : sd) {
                String line = index + "\t" + cs.time + "\t" + cs.censored + "\t" + cs.group + "\r\n";
                index++;
                fw.write(line);
            }
        }
        fw.close();
    }
    DecimalFormat df = new DecimalFormat("#.#");

    public void paintComponent(Graphics g) // draw graphics in the panel
    {
        int width = getWidth();             // width of window in pixels
        int height = getHeight();           // height of window in pixels
        setFigureDimensions();
        g.setColor(Color.white);
        g.clearRect(0, 0, width, height);

        super.paintComponent(g);            // call superclass to make panel display correctly

        drawLegend(g);
        drawSurvivalCurves(g);
        drawFigureLineInfo(g);
        // Drawing code goes here
    }

    private void drawFigureLineInfo(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        setRenderingHints(g2);
        g2.setColor(Color.BLACK);
        fm = getFontMetrics(getFont());
        int yoffset = fm.getHeight() * lineInfoList.size();

        int x = getTimeX(kmfi.figureLineInfoLowerPercentX * maxTime);
        int y = getPercentageY(kmfi.figureLineInfoLowerPercentY) - yoffset;

        for (String line : lineInfoList) {
            g2.drawString(line, x, y);
            y = y + fm.getHeight();
        }

    }

    private void drawSurvivalCurves(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        setRenderingHints(g2);
        g2.setStroke(kmfi.kmStroke);


        int colorIndex = 0;
        ArrayList<String> labels = new ArrayList<String>(sfi.getStrataInfoHashMap().keySet());
        Collections.sort(labels);

        LinkedHashMap<String, StrataInfo> strataInfoHashMap = sfi.getStrataInfoHashMap();

        for (String legend : labels) {
            StrataInfo si = strataInfoHashMap.get(legend);
            g2.setColor(kmfi.legendColor[colorIndex]);
            colorIndex++;

            for (int i = 0; i < si.getSurv().size() - 1; i++) {
                double p0time = si.getTime().get(i);
                double p1time = si.getTime().get(i + 1);
                double p0percentage = si.getSurv().get(i);
                double p1percentage = si.getSurv().get(i + 1);
                if (i == 0) {
                    g2.drawLine(getTimeX(0), getPercentageY(1), getTimeX(p0time), getPercentageY(1));
                    g2.drawLine(getTimeX(p0time), getPercentageY(1), getTimeX(p0time), getPercentageY(p0percentage));
                }
                g2.drawLine(getTimeX(p0time), getPercentageY(p0percentage), getTimeX(p1time), getPercentageY(p0percentage));

                g2.drawLine(getTimeX(p1time), getPercentageY(p0percentage), getTimeX(p1time), getPercentageY(p1percentage));
                // if (si.getStatus().get(i) == 0) {
                if (i > 0 && si.getNcens().get(i) > 0) {
                    g2.drawLine(getTimeX(p0time), getPercentageY(p0percentage) - 4, getTimeX(p0time), getPercentageY(p0percentage) + 4);
                    g2.drawLine(getTimeX(p0time) - 4, getPercentageY(p0percentage), getTimeX(p0time) + 4, getPercentageY(p0percentage));
                }
            }


        }

        String maxString = "";
        for (String legend : labels) {
            if (legend.length() > maxString.length()) {
                maxString = legend;
            }
        }

        int offset = fm.stringWidth(maxString);
        int x = getTimeX(kmfi.legendUpperPercentX * maxTime) - offset;
        int y = getPercentageY(kmfi.legendUpperPercentY);

        colorIndex = 0;
        for (String legend : labels) {
            g2.setColor(kmfi.legendColor[colorIndex]);
            colorIndex++;
            g2.drawLine(x - 20, y - (fm.getHeight() / 3), x - 5, y - (fm.getHeight() / 3));
            g2.drawString(legend, x, y);
            y = y + fm.getHeight();
        }


    }

    /**
     * Get the X coordinate based on a time value
     *
     * @param value
     * @return
     */
    private int getTimeX(double value) {
        double d = left + (((right - left) * value) / (maxTime - minTime));
        return (int) d;
    }

    /**
     * Get the Y coordinate based on percent value 0.0-1.0
     *
     * @param value
     * @return
     */
    private int getPercentageY(double value) {
        value = 1.0 - value;
        double d = top + (((bottom - top) * value) / (maxPercentage - minPercentage));
        return (int) d;
    }

    /**
     * @return the fileName
     */
    public String getFileName() {
        return fileName;
    }

    /**
     * @return the top
     */
    public int getTop() {
        return top;
    }

    /**
     * @return the bottom
     */
    public int getBottom() {
        return bottom;
    }

    /**
     * @return the left
     */
    public int getLeft() {
        return left;
    }

    /**
     * @return the right
     */
    public int getRight() {
        return right;
    }

    /**
     * @return the xAxisTimeValues
     */
    public ArrayList<Double> getxAxisTimeValues() {
        return xAxisTimeValues;
    }

    /**
     * @return the xAxisTimeValues
     */
    public ArrayList<Integer> getxAxisTimeCoordinates() {
        return xAxisTimeCoordinates;
    }

    class PlotInfo {

        double time;
        double atRisk;
        double censored;
        double events;
        double percentage;

        @Override
        public String toString() {
            return time + "\t" + atRisk + "\t" + censored + "\t" + events + "\t" + (atRisk - events) + "\t" + percentage;
        }
    }

    /**
     * Do higher quality rendering options
     *
     * @param g
     */
    private void setRenderingHints(Graphics2D g) {
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g.setRenderingHints(rh);

    }

    /**
     * Setup the axis, labels etc
     *
     * @param g
     */
    private void drawLegend(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        setRenderingHints(g2);
        g2.setColor(Color.BLACK);
        Font font = g2.getFont();
        Font f = new Font(font.getFontName(), Font.BOLD, font.getSize());
        g2.setFont(f);
        fm = getFontMetrics(f);
        int fontHeight = fm.getHeight();
        for (int i = 0; i < title.size(); i++) {
            if (fm.stringWidth(title.get(i)) > .8 * this.getWidth()) {
                f = new Font(font.getFontName(), Font.BOLD, 10);
                g2.setFont(f);
                fm = getFontMetrics(f);
            }
            g2.drawString(title.get(i), (getSize().width - fm.stringWidth(title.get(i))) / 2, ((i + 1) * fontHeight));
            // g2.setFont(font);
        }
        // draw the maxPercentage and minPercentage values
        String label = df.format(minPercentage);
        g2.drawString(label, left - 5 - (int) (fm.stringWidth(label)), bottom + titleHeight / 6);
        g2.drawLine(left - 5, bottom, left, bottom);
        double d = minPercentage + kmfi.yaxisPercentIncrement;
        //double graphHeight = top - bottom;

        while (d < maxPercentage) {
            int yvalue = bottom - (int) (d * (bottom - top));
            label = df.format(d * 100);
            g2.drawString(label, left - 5 - (int) (fm.stringWidth(label)), yvalue + titleHeight / 6); //

            g2.drawLine(left - 5, yvalue, left, yvalue);
            d = d + kmfi.yaxisPercentIncrement;
        }

        label = df.format(maxPercentage * 100);
        g2.drawString(label, left - 5 - (int) (fm.stringWidth(label)), top + (titleHeight) / 6);
        g2.drawLine(left - 5, top, left, top);

        // Create a rotation transformation for the font.
        AffineTransform fontAT = new AffineTransform();


        // Derive a new font using a rotatation transform
        fontAT.rotate(270 * java.lang.Math.PI / 180);
        Font theDerivedFont = f.deriveFont(fontAT);

        // set the derived font in the Graphics2D context
        g2.setFont(theDerivedFont);

        // Render a string using the derived font
        int yaxisHeight = fm.stringWidth(kmfi.yAxisLegend);
        g2.drawString(kmfi.yAxisLegend, (int) yaxisLabel, ((int) bottom - (int) (.5 * (bottom - top))) + yaxisHeight / 2);

        // put the original font back
        g2.setFont(f);



        double timeDistance = maxTime - minTime;
        double timeIncrement = timeDistance * kmfi.xaxisPercentIncrement;
        double timeInt = (int) Math.floor(timeIncrement);
        if (timeInt < 1.0) {
            timeInt = 1.0;
        }
        adjustedPercentIncrement = timeInt / timeDistance;

        d = adjustedPercentIncrement; //kmfi.xaxisPercentIncrement;
        xAxisTimeValues.clear();
        xAxisTimeCoordinates.clear();

        //if we don't have time values then use percentage to set time. Not perfect but allows different tics
        if (kmfi.xAxisLabels.isEmpty()) {
            xAxisTimeValues.add(minTime);
            xAxisTimeCoordinates.add(left);
            while (d <= 1.0) {
                double xaxisTime = ((minTime * kmfi.timeScale) + d * ((maxTime - minTime) * kmfi.timeScale)); //
                xAxisTimeValues.add(xaxisTime);

                Integer coordinate = left + (int) (d * (right - left));
                xAxisTimeCoordinates.add(coordinate);
                //       System.out.println(d + " " + left + " " + right + " " + coordinate + " " + minTime + " " + maxTime);
                d = d + adjustedPercentIncrement; //kmfi.xaxisPercentIncrement;
            }
        } else {
            minTime = kmfi.xAxisLabels.get(0);
            maxTime = kmfi.xAxisLabels.get(kmfi.xAxisLabels.size() - 1);
            for (Double xaxisTime : kmfi.xAxisLabels) {
                xAxisTimeValues.add(xaxisTime);
                d = (xaxisTime - minTime) / (maxTime - minTime);
                Integer coordinate = left + (int) (d * (right - left));
                xAxisTimeCoordinates.add(coordinate);
            }
        }

        for (int i = 0; i < xAxisTimeValues.size(); i++) {
            Double xaxisTime = xAxisTimeValues.get(i);
            Integer xCoordinate = xAxisTimeCoordinates.get(i);
            label = df.format(xaxisTime);
            if (i == xAxisTimeValues.size() - 1) {
                g2.drawString(label, xCoordinate - (fm.stringWidth(label)), bottom + fm.getHeight() + 5);
            } else {
                g2.drawString(label, xCoordinate - (fm.stringWidth(label) / 2), bottom + fm.getHeight() + 5);
            }
            g2.drawLine(xCoordinate, bottom, xCoordinate, bottom + 5);
        }

        // draw the vertical and horizontal lines
        g2.setStroke(kmfi.axisStroke);
        g2.drawLine(left, top, left, bottom);
        g2.drawLine(left, bottom, right, bottom);

        // draw xAxis legend
        g2.drawString(kmfi.xAxisLegend, getSize().width / 2 - (fm.stringWidth(kmfi.xAxisLegend) / 2), bottom + 2 * fm.getHeight() + 10);
    }
    Double adjustedPercentIncrement = 0.0;

    /**
     * Get the percentage increment for the time axis
     *
     * @return
     */
    public Double getTimeAxisIncrementPercentage() {
        return adjustedPercentIncrement;
    }

    /**
     * Reset the various bounds used to draw graph
     */
    private void setFigureDimensions() {
        fm = getFontMetrics(getFont());
        titleHeight = kmfi.titleHeight;//fm.getHeight();
        xAxisLabelHeight = titleHeight;
        labelWidth = Math.max(fm.stringWidth(df.format(minPercentage)),
                fm.stringWidth(df.format(maxPercentage))) + 5;
        top = kmfi.padding + titleHeight;
        bottom = this.getHeight() - kmfi.padding - xAxisLabelHeight;
        left = kmfi.padding + labelWidth + yaxisLabel;
        right = this.getWidth() - kmfi.padding;

    }

    /**
     * Combine the KM and Num risk into one image
     *
     * @param fileName
     */
    public void savePNGKMNumRisk(String fileName) {
        if (fileName.startsWith("null") || fileName.startsWith("Null") || fileName.startsWith("NULL")) {
            return;
        }
        this.fileName = fileName;

        NumbersAtRiskPanel numbersAtRiskPanel = new NumbersAtRiskPanel();
        numbersAtRiskPanel.setKaplanMeierFigure(this);
        numbersAtRiskPanel.setSize(this.getWidth(), numbersAtRiskPanel.getHeight());
        BufferedImage imageKM = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = imageKM.createGraphics();

        this.paint(graphics2D);

        BufferedImage imageNumRisk = new BufferedImage(numbersAtRiskPanel.getWidth(), numbersAtRiskPanel.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2DNumRisk = imageNumRisk.createGraphics();
        numbersAtRiskPanel.paint(graphics2DNumRisk);


        BufferedImage image = new BufferedImage(numbersAtRiskPanel.getWidth(), numbersAtRiskPanel.getHeight() + this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        g.drawImage(imageKM, 0, 0, null);
        g.drawImage(imageNumRisk, 0, this.getHeight(), null);

        try {
            ImageIO.write(image, "png", new File(fileName));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    /**
     *
     * @param fileName
     */
    public void savePNG(String fileName) {
        if (fileName.startsWith("null") || fileName.startsWith("Null") || fileName.startsWith("NULL")) {
            return;
        }
        this.fileName = fileName;
        BufferedImage image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = image.createGraphics();

        this.paint(graphics2D);
        try {
            ImageIO.write(image, "png", new File(fileName));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        try {

            KaplanMeierFigure kaplanMeierFigure = new KaplanMeierFigure();
            LinkedHashMap<String, ArrayList<CensorStatus>> survivalDataHashMap = new LinkedHashMap<String, ArrayList<CensorStatus>>();

//            if (false) { //http://sph.bu.edu/otlt/MPH-Modules/BS/BS704_Survival/
//                ArrayList<CensorStatus> graph1 = new ArrayList<CensorStatus>();
//                graph1.add(new CensorStatus("A", 24.0, "0"));
//                graph1.add(new CensorStatus("A", 3.0, "1"));
//                graph1.add(new CensorStatus("A", 11.0, "0"));
//                graph1.add(new CensorStatus("A", 19.0, "0"));
//                graph1.add(new CensorStatus("A", 24.0, "0"));
//                graph1.add(new CensorStatus("A", 13.0, "0"));
//
//                graph1.add(new CensorStatus("A", 14.0, "1"));
//                graph1.add(new CensorStatus("A", 2.0, "0"));
//                graph1.add(new CensorStatus("A", 18.0, "0"));
//                graph1.add(new CensorStatus("A", 17.0, "0"));
//                graph1.add(new CensorStatus("A", 24.0, "0"));
//                graph1.add(new CensorStatus("A", 21.0, "0"));
//                graph1.add(new CensorStatus("A", 12.0, "0"));
//
//                graph1.add(new CensorStatus("A", 1.0, "1"));
//                graph1.add(new CensorStatus("A", 10.0, "0"));
//                graph1.add(new CensorStatus("A", 23.0, "1"));
//                graph1.add(new CensorStatus("A", 6.0, "0"));
//                graph1.add(new CensorStatus("A", 5.0, "1"));
//                graph1.add(new CensorStatus("A", 9.0, "0"));
//                graph1.add(new CensorStatus("A", 17.0, "1"));
//
//                survivalDataHashMap.put("Label 1", graph1);
//
//
//
//            }


            if (true) {



                ArrayList<CensorStatus> graph1 = new ArrayList<CensorStatus>();
                graph1.add(new CensorStatus("A", 1.0, "1"));
                graph1.add(new CensorStatus("A", 1.0, "1"));
                graph1.add(new CensorStatus("A", 1.0, "1"));
                graph1.add(new CensorStatus("A", 2.0, "1"));
                graph1.add(new CensorStatus("A", 2.0, "1"));
                graph1.add(new CensorStatus("A", 3.0, "1"));

                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "1"));
                graph1.add(new CensorStatus("A", 4.0, "0"));

                graph1.add(new CensorStatus("A", 5.0, "1"));
                graph1.add(new CensorStatus("A", 5.0, "1"));

                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "0"));
                graph1.add(new CensorStatus("A", 8.0, "1"));

                graph1.add(new CensorStatus("A", 9.0, "1"));
                graph1.add(new CensorStatus("A", 9.0, "1"));
                graph1.add(new CensorStatus("A", 9.0, "1"));
                graph1.add(new CensorStatus("A", 9.0, "1"));
                graph1.add(new CensorStatus("A", 9.0, "1"));


                graph1.add(new CensorStatus("A", 13.0, "0"));
                graph1.add(new CensorStatus("A", 13.0, "0"));
                graph1.add(new CensorStatus("A", 13.0, "1"));

                survivalDataHashMap.put("Label 1", graph1);

                ArrayList<CensorStatus> graph2 = new ArrayList<CensorStatus>();
                graph2.add(new CensorStatus("A", 1.0, "1"));
                graph2.add(new CensorStatus("A", 1.0, "1"));
                graph2.add(new CensorStatus("A", 1.0, "0"));
                graph2.add(new CensorStatus("A", 3.0, "0"));
                graph2.add(new CensorStatus("A", 3.0, "1"));
                graph2.add(new CensorStatus("A", 4.0, "1"));

                graph2.add(new CensorStatus("A", 4.0, "1"));
                graph2.add(new CensorStatus("A", 4.0, "1"));
                graph2.add(new CensorStatus("A", 4.0, "1"));
                graph2.add(new CensorStatus("A", 5.0, "1"));
                graph2.add(new CensorStatus("A", 5.0, "0"));
                graph2.add(new CensorStatus("A", 5.0, "0"));
                graph2.add(new CensorStatus("A", 5.0, "0"));

                graph2.add(new CensorStatus("A", 6.0, "1"));
                graph2.add(new CensorStatus("A", 6.0, "0"));

                graph2.add(new CensorStatus("A", 7.0, "0"));
                graph2.add(new CensorStatus("A", 7.0, "0"));
                graph2.add(new CensorStatus("A", 7.0, "0"));
                graph2.add(new CensorStatus("A", 7.0, "0"));
                graph2.add(new CensorStatus("A", 8.0, "1"));
                graph2.add(new CensorStatus("A", 8.0, "1"));
                graph2.add(new CensorStatus("A", 8.0, "1"));

                graph2.add(new CensorStatus("A", 8.0, "1"));
                graph2.add(new CensorStatus("A", 8.0, "1"));
                graph2.add(new CensorStatus("A", 8.0, "0"));
                graph2.add(new CensorStatus("A", 9.0, "0"));
                graph2.add(new CensorStatus("A", 9.0, "1"));


                graph2.add(new CensorStatus("A", 10.0, "0"));
                graph2.add(new CensorStatus("A", 10.0, "0"));
                graph2.add(new CensorStatus("A", 10.0, "0"));

                survivalDataHashMap.put("Label 2", graph2);
            }

            ArrayList<String> figureInfo = new ArrayList<String>();
            //DecimalFormat dfe = new DecimalFormat("0.00E0");
            //DecimalFormat df = new DecimalFormat("0.00");



            JFrame application = new JFrame();
            application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            application.add(kaplanMeierFigure);
            kaplanMeierFigure.setSize(500, 400);

            application.setSize(500, 400);         // window is 500 pixels wide, 400 high
            application.setVisible(true);

            ArrayList<String> titles = new ArrayList<String>();
            titles.add("Line 1");
            titles.add("line 2");
            kaplanMeierFigure.setSurvivalData(titles, survivalDataHashMap, true);

            //   figureInfo.add("HR=2.1 95% CI(1.8-2.5)");
            //   figureInfo.add("p-value=.001");
            kaplanMeierFigure.setFigureLineInfo(figureInfo);

            kaplanMeierFigure.savePNGKMNumRisk("/Users/Scooter/Downloads/test.png");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
