There is no accepted sort order for variants at the same reference position. This class adjusts sort order in such cases so that variants at the same reference position are locally sorted shortest first. This is primarily useful when performing merge operations. Assumes that input variants are other
| 44 | * merge operations. Assumes that input variants are otherwise sorted within chromosomes. |
| 45 | */ |
| 46 | public class VcfSortRefiner implements VcfIterator { |
| 47 | |
| 48 | private final VcfIterator mIn; |
| 49 | private final PriorityQueue<VcfRecord> mCurrent = new PriorityQueue<>(1, IntervalComparator.SINGLETON); |
| 50 | private VcfRecord mNext; |
| 51 | |
| 52 | /** |
| 53 | * Wraps around an existing VCF reader. |
| 54 | * |
| 55 | * @param in where to read from |
| 56 | * @throws IOException when IO or format errors occur. |
| 57 | */ |
| 58 | public VcfSortRefiner(VcfIterator in) throws IOException { |
| 59 | mIn = new VcfFilterIterator(in, new AssertVcfSorted()); |
| 60 | if (mIn.hasNext()) { |
| 61 | mNext = mIn.next(); |
| 62 | setNext(); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | @Override |
| 67 | public VcfHeader getHeader() { |
| 68 | return mIn.getHeader(); |
| 69 | } |
| 70 | |
| 71 | |
| 72 | @Override |
| 73 | public boolean hasNext() { |
| 74 | return mCurrent.size() != 0; |
| 75 | } |
| 76 | |
| 77 | @Override |
| 78 | public VcfRecord next() throws IOException { |
| 79 | if (mCurrent.size() == 0) { |
| 80 | throw new IllegalStateException("No more records"); |
| 81 | } |
| 82 | final VcfRecord rec = mCurrent.poll(); |
| 83 | setNext(); |
| 84 | return rec; |
| 85 | } |
| 86 | |
| 87 | /** |
| 88 | * Fill the queue for the current position if need be. |
| 89 | * @throws IOException when IO or format errors occur. |
| 90 | */ |
| 91 | private void setNext() throws IOException { |
| 92 | if (mCurrent.isEmpty() && mNext != null) { |
| 93 | final String chr = mNext.getSequenceName(); |
| 94 | final int pos = mNext.getStart(); |
| 95 | mCurrent.add(mNext); |
| 96 | mNext = null; |
| 97 | while (mIn.hasNext()) { // Get additional records at same position |
| 98 | final VcfRecord rec = mIn.next(); |
| 99 | if (rec.getStart() != pos || !rec.getSequenceName().equals(chr)) { |
| 100 | mNext = rec; |
| 101 | break; |
| 102 | } |
| 103 | mCurrent.add(rec); |
nothing calls this directly
no outgoing calls
no test coverage detected