diff --git a/uk/ac/sanger/artemis/components/variant/AbstractVCFReader.java b/uk/ac/sanger/artemis/components/variant/AbstractVCFReader.java index 4fd7c1e519761c39ae1a72b649efd44b6268623b..08257af372f1557dac889091f179ca10562723fb 100644 --- a/uk/ac/sanger/artemis/components/variant/AbstractVCFReader.java +++ b/uk/ac/sanger/artemis/components/variant/AbstractVCFReader.java @@ -30,12 +30,59 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import uk.ac.sanger.artemis.components.variant.BCFReader.BCFReaderIterator; + public abstract class AbstractVCFReader { private boolean vcf_v4 = false; protected abstract String[] getSeqNames(); protected abstract String getFileName(); + private BCFReaderIterator bcfIterator = null; + private TabixReader.Iterator tabixIterator = null; + + /** + * Read and return the next record. + * @param chr sequence name + * @param sbeg start base + * @param send end base + * @return + * @throws IOException + */ + public VCFRecord getNextRecord(String chr, int sbeg, int send) throws IOException + { + VCFRecord record; + if(this instanceof BCFReader) + { + if(bcfIterator == null) + bcfIterator = ((BCFReader)this).query(chr, sbeg, send); + + record = bcfIterator.next(); + if(record == null) + bcfIterator = null; + } + else + { + if(tabixIterator == null) + tabixIterator = ((TabixReader)this).query(chr+":"+sbeg+"-"+send); + if(tabixIterator == null) + return null; + + String s = tabixIterator.next(); + if(s == null) + { + tabixIterator = null; + return null; + } + record = VCFRecord.parse(s); + + if(record == null) + tabixIterator = null; + } + return record; + } + + protected static int readInt(final InputStream is) throws IOException { byte[] buf = new byte[4]; is.read(buf); diff --git a/uk/ac/sanger/artemis/components/variant/IOUtils.java b/uk/ac/sanger/artemis/components/variant/IOUtils.java index dc7b6aabdd776ea484000c5c4a0cc9fa92e83508..e62ac259a4c3a97bec4d0a772fc92523fc52bcee 100644 --- a/uk/ac/sanger/artemis/components/variant/IOUtils.java +++ b/uk/ac/sanger/artemis/components/variant/IOUtils.java @@ -30,13 +30,20 @@ import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.net.URL; +import java.util.Comparator; import java.util.List; +import java.util.Vector; import javax.swing.Box; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFileChooser; +import javax.swing.JFrame; import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import uk.ac.sanger.artemis.Entry; import uk.ac.sanger.artemis.EntryGroup; @@ -591,12 +598,11 @@ class IOUtils { boolean vcf_v4 = reader.isVcf_v4(); int len = basesStr.length(); - - if (reader instanceof BCFReader) + + try { - BCFReaderIterator it = ((BCFReader) reader).query(chr, sbeg, send); VCFRecord record; - while ((record = it.next()) != null) + while ((record = reader.getNextRecord(chr, sbeg, send)) != null) { int basePosition = record.getPos() + vcfView.getSequenceOffset(record.getChrom()); if(vcfView.showVariant(record, features, basePosition, vcf_v4) ) @@ -609,7 +615,7 @@ class IOUtils basesStr = basesStr.substring(0, position) + 'n' + basesStr.substring(position+1); } - + if(basesStr.length() > len) // adjust for insertions { sbeg -= (basesStr.length()-len); @@ -617,41 +623,133 @@ class IOUtils } } } - else + catch(NullPointerException e) { - try + System.err.println(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); + } + + return basesStr; + } + + + protected static void countVariants(final VCFview vcfView, + final FeatureVector features) throws IOException + { + String[] columnNames = { + "VCF", "Name", "Variant", "Non-variant", "Deletion", "Insertion", "Synonymous", "Non-synonymous"}; + Vector<String> columnData = new Vector<String>(); + for(String col: columnNames) + columnData.add(col); + Vector<Vector<Object>> rowData = new Vector<Vector<Object>>(); + + AbstractVCFReader vcfReaders[] = vcfView.getVcfReaders(); + for (AbstractVCFReader reader: vcfReaders) + { + + for (int j = 0; j < features.size(); j++) { - TabixReader.Iterator iter = - (((TabixReader) reader).query(chr+":"+sbeg+"-"+send)); // get the iterator - String s; - while (iter != null && (s = iter.next()) != null) + int count[] = new int[6]; + for(int c: count) + c = 0; + + Feature f = features.elementAt(j); + FeatureSegmentVector segs = f.getSegments(); + + for(int k=0; k<segs.size(); k++) { - VCFRecord record = VCFRecord.parse(s); - int basePosition = record.getPos() + vcfView.getSequenceOffset(record.getChrom()); - if(vcfView.showVariant(record, features, basePosition, vcf_v4) ) - basesStr = getSeqsVariation(record, basesStr, sbeg, isFwd, vcf_v4); - else if(useNs && isSNPorNonVariant(record)) + FeatureSegment seg = segs.elementAt(k); + int sbeg = seg.getRawRange().getStart(); + int send = seg.getRawRange().getEnd(); + + if(vcfView.isConcatenate()) { - int position = record.getPos()-sbeg; - if(!isFwd) - position = basesStr.length()-position-1; - basesStr = basesStr.substring(0, position) + 'n' + - basesStr.substring(position+1); + String[] contigs = reader.getSeqNames(); + for(int i=0; i<contigs.length; i++) + { + int offset = vcfView.getSequenceOffset(contigs[i]); + int nextOffset; + if(i<contigs.length-1) + nextOffset = vcfView.getSequenceOffset(contigs[i+1]); + else + nextOffset = vcfView.seqLength; + + if( (offset >= sbeg && offset < send) || + (offset < sbeg && sbeg < nextOffset) ) + { + int thisStart = sbeg - offset; + if(thisStart < 1) + thisStart = 1; + int thisEnd = send - offset; + + VCFRecord record; + while ((record = reader.getNextRecord(vcfView.getChr(), thisStart, thisEnd)) != null) + count(record, count, features, reader); + } + } } - - if(basesStr.length() > len) // adjust for insertions + else { - sbeg -= (basesStr.length()-len); - len = basesStr.length(); + VCFRecord record; + while ((record = reader.getNextRecord(vcfView.getChr(), sbeg, send)) != null) + count(record, count, features, reader); } } + + Object row[] = { + reader.getName(), f.getSystematicName(), count[0], count[1], count[2], count[3], count[4], count[5] }; + + Vector<Object> thisRow = new Vector<Object>(); + for(Object obj: row) + thisRow.add(obj); + rowData.add(thisRow); } - catch(NullPointerException e) - { - System.err.println(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); + } + + JTable variantData = new JTable(rowData, columnData); + TableRowSorter<TableModel> sorter = + new TableRowSorter<TableModel>(variantData.getModel()); + variantData.setRowSorter(sorter); + + Comparator<Integer> comparator = new Comparator<Integer>() { + public int compare(Integer i1, Integer i2) { + return i1.compareTo(i2); } + }; + + for(int i=2; i< columnData.size(); i++) + sorter.setComparator(i, comparator); + + JScrollPane jsp = new JScrollPane(variantData); + JFrame f = new JFrame("Variant Overview"); + f.getContentPane().add(jsp); + f.pack(); + f.setVisible(true); + } + + private static void count(VCFRecord record, int count[], FeatureVector features, AbstractVCFReader reader) + { + if(record.getAlt().isNonVariant()) + { + count[1]++; + return; } - return basesStr; + else + count[0]++; + + if(record.getAlt().isDeletion(reader.isVcf_v4())) + count[2]++; + else if(record.getAlt().isInsertion(reader.isVcf_v4())) + count[3]++; + + if(record.getAlt().length() == 1 && record.getRef().length() == 1) + { + short synFlag = record.getSynFlag(features, record.getPos()); + switch(synFlag) + { + case 1: count[4]++; break; // synonymous + default: count[5]++; break; // non-synonymous + } + } } private static boolean isSNPorNonVariant(VCFRecord record) @@ -876,33 +974,18 @@ class IOUtils { boolean vcf_v4 = reader.isVcf_v4(); Key variantKey = new Key("misc_difference"); - if (reader instanceof BCFReader) + try { - BCFReaderIterator it = ((BCFReader) reader).query(chr, sbegc, sendc); VCFRecord record; - while ((record = it.next()) != null) + while( (record = reader.getNextRecord(chr, sbegc, sendc)) != null) { makeFeature(record, reader.getName(), vcfView, features, bases, entry, variantKey, vcf_v4); } } - else + catch (NullPointerException e) { - try - { - TabixReader.Iterator iter = (((TabixReader) reader).query(chr + ":" - + sbegc + "-" + sendc)); // get the iterator - String s; - while (iter != null && (s = iter.next()) != null) - { - VCFRecord record = VCFRecord.parse(s); - makeFeature(record, reader.getName(), vcfView, features, bases, entry, variantKey, vcf_v4); - } - } - catch (NullPointerException e) - { - System.err.println(chr + ":" + sbegc + "-" + sendc + "\n" - + e.getMessage()); - } + System.err.println(chr + ":" + sbegc + "-" + sendc + "\n" + + e.getMessage()); } } diff --git a/uk/ac/sanger/artemis/components/variant/VCFview.java b/uk/ac/sanger/artemis/components/variant/VCFview.java index ee225fa48b23850152f43f6d4e7bcabea6c631d9..31070f18175f505d248354a573489c5ede4a5679 100644 --- a/uk/ac/sanger/artemis/components/variant/VCFview.java +++ b/uk/ac/sanger/artemis/components/variant/VCFview.java @@ -666,6 +666,24 @@ public class VCFview extends JPanel } }); + final JMenuItem snpOverview = new JMenuItem("Overview"); + popup.add(snpOverview); + snpOverview.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + try + { + IOUtils.countVariants(VCFview.this, selection.getAllFeatures()); + } + catch (IOException e1) + { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + }); + final JCheckBoxMenuItem labels = new JCheckBoxMenuItem("Show Labels", showLabels); labels.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) @@ -1017,43 +1035,17 @@ public class VCFview extends JPanel float pixPerBase, FeatureVector features) { - String s; cacheVariantLines = new Vector<Integer>(5); - if(vcfReaders[i] instanceof BCFReader) + try { - try - { - BCFReader bcfReader = (BCFReader)vcfReaders[i]; - BCFReaderIterator it = bcfReader.query(chr, sbeg, send); - VCFRecord bcfRecord; - while((bcfRecord = it.next()) != null) - drawVariantCall(g, bcfRecord, start, i, pixPerBase, features, vcfReaders[i].isVcf_v4()); - } - catch (IOException e) - { - logger4j.warn(e.getMessage()); - e.printStackTrace(); - } - + VCFRecord record; + while((record = vcfReaders[i].getNextRecord(chr, sbeg, send)) != null) + drawVariantCall(g, record, start, i, pixPerBase, features, vcfReaders[i].isVcf_v4()); } - else + catch (IOException e) { - try - { - TabixReader.Iterator iter = - ((TabixReader)vcfReaders[i]).query(chr+":"+sbeg+"-"+send); // get the iterator - if (iter == null) - return; - while (iter != null && (s = iter.next()) != null) - { - VCFRecord vcfRecord = VCFRecord.parse(s); - drawVariantCall(g, vcfRecord, start, i, pixPerBase, features, vcfReaders[i].isVcf_v4()); - } - } - catch (Exception e) - { - logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); - } + logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); + e.printStackTrace(); } } @@ -1387,41 +1379,16 @@ public class VCFview extends JPanel Point mousePoint, FeatureVector features, int start, float pixPerBase) { - if(vcfReaders[i] instanceof BCFReader) + try { - try - { - BCFReader bcfReader = (BCFReader)vcfReaders[i]; - BCFReaderIterator it = bcfReader.query(chr, sbeg, send); - VCFRecord bcfRecord; - while((bcfRecord = it.next()) != null) - isMouseOver(mousePoint, bcfRecord, features, i, start, pixPerBase, vcfReaders[i].isVcf_v4()); - } - catch (IOException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } + VCFRecord bcfRecord; + while((bcfRecord = vcfReaders[i].getNextRecord(chr, sbeg, send)) != null) + isMouseOver(mousePoint, bcfRecord, features, i, start, pixPerBase, vcfReaders[i].isVcf_v4()); } - else + catch (IOException e) { - try - { - TabixReader.Iterator iter = - ((TabixReader)vcfReaders[i]).query(chr+":"+sbeg+"-"+send); // get the iterator - if (iter == null) - return; - String s; - while ((s = iter.next()) != null) - { - VCFRecord vcfRecord = VCFRecord.parse(s); - isMouseOver(mousePoint, vcfRecord, features, i, start, pixPerBase, vcfReaders[i].isVcf_v4()); - } - } - catch (Exception e) - { - logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); - } + logger4j.warn(chr+":"+sbeg+"-"+send+"\n"+e.getMessage()); + e.printStackTrace(); } }