/** * Copyright Copyright 2014 Simon Andrews * * This file is part of BamQC. * * BamQC 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. * * BamQC 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 BamQC; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Changelog: * - Piero Dalle Pezze: Corrected null pointer exception * - Simon Andrews: Class creation. */ package uk.ac.babraham.BamQC.Modules; import java.awt.GridLayout; import java.io.IOException; import java.util.List; import javax.swing.JPanel; import javax.xml.stream.XMLStreamException; import org.apache.log4j.Logger; import net.sf.samtools.Cigar; import net.sf.samtools.CigarElement; import net.sf.samtools.CigarOperator; import net.sf.samtools.SAMRecord; import uk.ac.babraham.BamQC.DataTypes.Genome.AnnotationSet; import uk.ac.babraham.BamQC.Graphs.LineGraph; import uk.ac.babraham.BamQC.Report.HTMLReportArchive; import uk.ac.babraham.BamQC.Sequence.SequenceFile; /** * @author Simon Andrews * @author Piero Dalle Pezze * */ public class SoftClipDistribution extends AbstractQCModule { // logger private static Logger log = Logger.getLogger(SoftClipDistribution.class); private long [] leftClipCounts = new long[1]; private long [] rightClipCounts = new long[1]; @Override public void processSequence(SAMRecord read) { if (read.getReadUnmappedFlag()) return; int leftClip = 0; int rightClip = 0; // Get the CIGAR list Cigar cigar = read.getCigar(); if (cigar == null || read.getCigarLength() == 0) { log.debug("Read " + read.getReadString() + " does not have Cigar string."); return; } List<CigarElement> elements = cigar.getCigarElements(); CigarElement first = elements.get(0); CigarElement last = elements.get(elements.size()-1); if (first.getOperator().equals(CigarOperator.S)) { if (read.getReadNegativeStrandFlag()) { rightClip = first.getLength(); } else { leftClip = first.getLength(); } } if (last.getOperator().equals(CigarOperator.S)) { if (read.getReadNegativeStrandFlag()) { leftClip = last.getLength(); } else { rightClip = last.getLength(); } } int max=leftClip; if (rightClip>leftClip)max=rightClip; if (max+1 > leftClipCounts.length) expandCounts(max+1); leftClipCounts[leftClip]++; rightClipCounts[rightClip]++; } private void expandCounts (int newLen) { long [] temp = new long[newLen]; for (int i=0;i<leftClipCounts.length;i++) { temp[i] = leftClipCounts[i]; } leftClipCounts = temp; temp = new long[newLen]; for (int i=0;i<rightClipCounts.length;i++) { temp[i] = rightClipCounts[i]; } rightClipCounts = temp; } @Override public void processFile(SequenceFile file) {} @Override public void processAnnotationSet(AnnotationSet annotation) {} @Override public JPanel getResultsPanel() { JPanel resultsPanel = new JPanel(); resultsPanel.setLayout(new GridLayout(2,1)); String [] labels = new String[leftClipCounts.length]; double [][] leftData = new double[1][leftClipCounts.length]; double [][] rightData = new double[1][leftClipCounts.length]; double maxLeft=1; double maxRight=1; for (int i=0;i<leftClipCounts.length;i++) { labels[i] = ""+i; leftData[0][i] = leftClipCounts[i]; rightData[0][i] = rightClipCounts[i]; if (leftData[0][i] > maxLeft) maxLeft = leftData[0][i]; if (rightData[0][i] > maxRight) maxRight = rightData[0][i]; } resultsPanel.add(new LineGraph(leftData, 0, maxLeft, "Clip Length", "Clip Number", new String[]{"Left (5') clips"}, labels,"Soft Clip Distribution at the Left (5') End")); resultsPanel.add(new LineGraph(rightData, 0, maxRight, "Clip Length", "Clip Number", new String[]{"Right (3') clips"},labels, "Soft Clip Distribution at the Right (3') End")); return (resultsPanel); } @Override public String name() { return "Soft Clip Length Distributions"; } @Override public String description() { return "Looks at how much of your reads have been soft clipped"; } @Override public void reset() { leftClipCounts = new long[1]; rightClipCounts = new long[1]; } @Override public boolean raisesError() { return false; } @Override public boolean raisesWarning() { return false; } @Override public boolean needsToSeeSequences() { return true; } @Override public boolean needsToSeeAnnotation() { return false; } @Override public boolean ignoreInReport() { if(ModuleConfig.getParam("SoftClipDistribution", "ignore") > 0 || (leftClipCounts.length==1 && rightClipCounts.length==1)) return true; return false; } @Override public void makeReport(HTMLReportArchive report) throws XMLStreamException, IOException { super.writeDefaultImage(report, "soft_clip_distribution_graph.png","Soft Clipping Distribution Graph", 800, 600); StringBuffer sb = report.dataDocument(); sb.append("Length\t5'_count\t3'_count\n"); for (int i=0;i<leftClipCounts.length;i++) { sb.append(i); sb.append("\t"); sb.append(leftClipCounts[i]); sb.append("\t"); sb.append(rightClipCounts[i]); sb.append("\n"); } } public long[] getLeftClipCounts() { return leftClipCounts; } public long[] getRightClipCounts() { return rightClipCounts; } }