org.gwaspi.reports.PlinkReportLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.gwaspi.reports.PlinkReportLoader.java

Source

/*
 * Copyright (C) 2013 Universitat Pompeu Fabra
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.gwaspi.reports;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.labels.AbstractXYItemLabelGenerator;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.CombinedRangeXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.TextAnchor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * ASSOC File columns
 *   CHR     Chromosome
 *   SNP     SNP ID
 *   BP      Physical position (base-pair)
 *   A1      Minor allele name (based on whole sample)
 *   F_A     Frequency of this allele in cases
 *   F_U     Frequency of this allele in controls
 *   A2      Major allele name
 *   CHISQ   Basic allelic test chi-square (1df)
 *   P       Asymptotic p-value for this test
 *   OR      Estimated odds ratio (for A1, i.e. A2 is reference)
 */
public class PlinkReportLoader {

    private static final Logger log = LoggerFactory.getLogger(PlinkReportLoader.class);

    private static Map<String, String> labeler = new HashMap<String, String>();

    private PlinkReportLoader() {
    }

    public static CombinedRangeXYPlot loadAssocUnadjLogPvsPos(File plinkReport, Set<String> redMarkersHS)
            throws IOException {

        XYSeriesCollection chrData = new XYSeriesCollection();

        NumberAxis sharedAxis = new NumberAxis("-log?(P)");

        CombinedRangeXYPlot combinedPlot = new CombinedRangeXYPlot(sharedAxis);
        combinedPlot.setGap(0);

        XYSeries series1 = null;
        XYSeries series2 = null;

        FileReader inputFileReader = null;
        BufferedReader inputBufferReader = null;
        String tempChr = null;
        try {
            inputFileReader = new FileReader(plinkReport);
            inputBufferReader = new BufferedReader(inputFileReader);

            // Getting data from file and subdividing to series all points by chromosome
            String l;
            tempChr = "";
            String header = inputBufferReader.readLine();
            int count = 0;
            while ((l = inputBufferReader.readLine()) != null) {

                if (count % 10000 == 0) {
                    log.info("loadAssocUnadjLogPvsPos -> reader count: {}", count);
                }
                count++;

                l = l.trim().replaceAll("\\s+", ",");
                String[] cVals = l.split(",");

                String markerId = cVals[1];
                int position = Integer.parseInt(cVals[2]);
                String s_pVal = cVals[8];

                if (!s_pVal.equals("NA")) {
                    double logPValue = Math.abs(Math.log(Double.parseDouble(s_pVal)) / Math.log(10));

                    if (cVals[0].toString().equals(tempChr)) {
                        if (redMarkersHS.contains(markerId)) {
                            series2.add(position, logPValue);
                        } else {
                            series1.add(position, logPValue);
                        }
                        labeler.put(tempChr + "_" + position, markerId);
                    } else {
                        if (!tempChr.isEmpty()) { // SKIP FIRST TIME (NO DATA YET!)
                            chrData.addSeries(series1);
                            chrData.addSeries(series2);
                            appendToCombinedRangePlot(combinedPlot, tempChr, chrData);
                        }
                        tempChr = cVals[0];
                        series1 = new XYSeries("Imputed");
                        series2 = new XYSeries("Observed");
                        labeler.put(tempChr + "_" + position, markerId);

                        if (redMarkersHS.contains(markerId)) {
                            series2.add(position, logPValue);
                        } else {
                            series1.add(position, logPValue);
                        }
                    }
                }
            }
        } finally {
            if (inputBufferReader != null) {
                inputBufferReader.close();
            } else if (inputFileReader != null) {
                inputFileReader.close();
            }
        }

        chrData.addSeries(series1);
        chrData.addSeries(series2);
        appendToCombinedRangePlot(combinedPlot, tempChr, chrData); // ADD LAST CHR TO PLOT

        return combinedPlot;
    }

    private static void appendToCombinedRangePlot(CombinedRangeXYPlot combinedPlot, String chromosome,
            XYSeriesCollection seriesCol) {
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, true);
        renderer.setSeriesPaint(0, Color.blue);

        JFreeChart subchart = ChartFactory.createScatterPlot("", "Chr " + chromosome, "", seriesCol,
                PlotOrientation.VERTICAL, true, false, false);

        XYPlot subplot = (XYPlot) subchart.getPlot();
        subplot.setRenderer(renderer);
        subplot.setBackgroundPaint(null);

        subplot.setDomainGridlineStroke(new BasicStroke(0.0f));
        subplot.setDomainMinorGridlineStroke(new BasicStroke(0.0f));
        subplot.setDomainGridlinePaint(Color.blue);
        subplot.setRangeGridlineStroke(new BasicStroke(0.0f));
        subplot.setRangeMinorGridlineStroke(new BasicStroke(0.0f));
        subplot.setRangeGridlinePaint(Color.blue);

        NumberAxis chrAxis = (NumberAxis) subplot.getDomainAxis();
        chrAxis.setAxisLineVisible(true);
        chrAxis.setTickLabelsVisible(true);
        chrAxis.setTickMarksVisible(true);
        chrAxis.setTickUnit(new NumberTickUnit(10000));
        chrAxis.setAutoRangeIncludesZero(false);

        NumberAxis log10Axis = (NumberAxis) subplot.getRangeAxis();
        log10Axis.setTickMarkInsideLength(2.0f);
        log10Axis.setTickMarkOutsideLength(2.0f);
        log10Axis.setMinorTickCount(2);
        log10Axis.setMinorTickMarksVisible(true);
        log10Axis.setAxisLineVisible(true);
        log10Axis.setAutoRangeIncludesZero(false);

        XYItemRenderer lblRenderer = subplot.getRenderer();
        MySeriesItemLabelGenerator lblGenerator = new MySeriesItemLabelGenerator(4.0d, chromosome);

        lblRenderer.setSeriesItemLabelGenerator(0, lblGenerator);
        lblRenderer.setSeriesItemLabelGenerator(1, lblGenerator);
        lblRenderer.setSeriesItemLabelFont(0, new Font("Serif", Font.PLAIN, 12));
        lblRenderer.setSeriesItemLabelFont(1, new Font("Serif", Font.PLAIN, 12));
        lblRenderer.setSeriesPositiveItemLabelPosition(0, new ItemLabelPosition(ItemLabelAnchor.CENTER,
                TextAnchor.BOTTOM_LEFT, TextAnchor.TOP_LEFT, -Math.PI / 4.0));
        lblRenderer.setSeriesPositiveItemLabelPosition(1, new ItemLabelPosition(ItemLabelAnchor.CENTER,
                TextAnchor.BOTTOM_LEFT, TextAnchor.TOP_LEFT, -Math.PI / 4.0));
        lblRenderer.setSeriesItemLabelsVisible(0, true);
        lblRenderer.setSeriesItemLabelsVisible(1, true);

        combinedPlot.add(subplot, 1);
    }

    private static class MySeriesItemLabelGenerator extends AbstractXYItemLabelGenerator
            implements XYItemLabelGenerator {

        private double threshold;
        private String chr;

        /**
         * Creates a new generator that only displays labels that are greater
         * than or equal to the threshold value.
         *
         * @param threshold the threshold value.
         */
        MySeriesItemLabelGenerator(double threshold, String chr) {
            this.threshold = threshold;
            this.chr = chr;
        }

        /**
         * Generates a label for the specified item. The label is typically a
         * formatted version of the data value, but any text can be used.
         *
         * @param dataset the dataset (<code>null</code> not permitted).
         * @param series the series index (zero-based).
         * @param category the category index (zero-based).
         *
         * @return the label (possibly <code>null</code>).
         */
        public String generateLabel(XYDataset dataset, int series, int item) {
            String result = null;
            Number value = dataset.getYValue(series, item);
            int position = (int) dataset.getXValue(series, item);
            if (value != null) {
                double v = value.doubleValue();
                if (v > this.threshold) {
                    StringBuilder chrPos = new StringBuilder(chr);
                    chrPos.append("_");
                    chrPos.append(position);
                    result = labeler.get(chrPos.toString()).toString();

                    //result = value.toString().substring(0, 4);  // could apply formatting here
                }
            }
            return result;
        }
    }
}