diff --git a/pom.xml b/pom.xml index d925f88f3..91deedac4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ au.edu.wehi gridss jar - 1.1.0 + 1.1.1 gridss https://github.com/PapenfussLab/gridss diff --git a/src/main/java/au/edu/wehi/idsv/MaximalEvidenceCliqueIterator.java b/src/main/java/au/edu/wehi/idsv/MaximalEvidenceCliqueIterator.java index e1273d425..e1a079acb 100644 --- a/src/main/java/au/edu/wehi/idsv/MaximalEvidenceCliqueIterator.java +++ b/src/main/java/au/edu/wehi/idsv/MaximalEvidenceCliqueIterator.java @@ -19,11 +19,11 @@ * @author Daniel Cameron * */ -public class MaximalEvidenceCliqueIterator extends AbstractIterator { +public class MaximalEvidenceCliqueIterator extends AbstractIterator { private static final Log log = Log.getInstance(MaximalEvidenceCliqueIterator.class); public static final String BREAKEND_ID_SUFFIX_HIGH = "h"; public static final String BREAKEND_ID_SUFFIX_LOW = "o"; - private VariantContextDirectedEvidence lastHigh = null; + private VariantContextDirectedBreakpoint lastHigh = null; private final BreakendDirection targetLowDir; private final BreakendDirection targetHighDir; private final RectangleGraphMaximalCliqueIterator calc; @@ -102,7 +102,7 @@ private RectangleGraphNode toGraphNode(DirectedEvidence e) { if (lowDir != targetLowDir || highDir != targetHighDir) return null; return node; } - private VariantContextDirectedEvidence toVariant(String event, RectangleGraphNode node, BreakpointSummary breakpoint, boolean isHighBreakend) { + private VariantContextDirectedBreakpoint toVariant(String event, RectangleGraphNode node, BreakpointSummary breakpoint, boolean isHighBreakend) { IdsvVariantContextBuilder builder = new IdsvVariantContextBuilder(context); builder.attribute(VcfSvConstants.BREAKEND_EVENT_ID_KEY, event); builder.attribute(VcfSvConstants.PARTNER_BREAKEND_ID_KEY, event + (isHighBreakend ? BREAKEND_ID_SUFFIX_LOW : BREAKEND_ID_SUFFIX_HIGH)); @@ -115,7 +115,7 @@ private VariantContextDirectedEvidence toVariant(String event, RectangleGraphNod double weight = ScalingHelper.toUnscaledWeight(scaledWeight); builder.phredScore(weight); builder.attribute(VcfAttributes.CALLED_QUAL, weight); - VariantContextDirectedEvidence v = (VariantContextDirectedBreakpoint)builder.make(); + VariantContextDirectedBreakpoint v = (VariantContextDirectedBreakpoint)builder.make(); assert(v != null); return v; } @@ -140,9 +140,9 @@ private BreakpointSummary toBreakpointSummary(RectangleGraphNode node) { return breakpoint; } @Override - protected VariantContextDirectedEvidence computeNext() { + protected VariantContextDirectedBreakpoint computeNext() { if (lastHigh != null) { - VariantContextDirectedEvidence result = lastHigh; + VariantContextDirectedBreakpoint result = lastHigh; lastHigh = null; return result; } @@ -150,7 +150,7 @@ protected VariantContextDirectedEvidence computeNext() { RectangleGraphNode node = calc.next(); BreakpointSummary breakpoint = toBreakpointSummary(node); String id = idGenerator.generate(breakpoint); - VariantContextDirectedEvidence result = toVariant(id, node, breakpoint, false); + VariantContextDirectedBreakpoint result = toVariant(id, node, breakpoint, false); lastHigh = toVariant(id, node, breakpoint, true); return result; } diff --git a/src/main/java/au/edu/wehi/idsv/VariantCallIterator.java b/src/main/java/au/edu/wehi/idsv/VariantCallIterator.java index e2357c410..335d71dd5 100644 --- a/src/main/java/au/edu/wehi/idsv/VariantCallIterator.java +++ b/src/main/java/au/edu/wehi/idsv/VariantCallIterator.java @@ -18,7 +18,7 @@ * * @author Daniel Cameron */ -public class VariantCallIterator implements CloseableIterator { +public class VariantCallIterator implements CloseableIterator { private static final List> DIRECTION_ORDER = ImmutableList.of( Pair.of(BreakendDirection.Forward, BreakendDirection.Forward), Pair.of(BreakendDirection.Forward, BreakendDirection.Backward), @@ -28,7 +28,7 @@ public class VariantCallIterator implements CloseableIterator> iteratorGenerator; private final QueryInterval filterInterval; - private Iterator currentIterator; + private Iterator currentIterator; private int currentDirectionOrdinal; public VariantCallIterator(ProcessingContext processContext, Iterable evidence) throws InterruptedException { this.processContext = processContext; @@ -68,8 +68,9 @@ private void reinitialiseIterator() { idGenerator); if (filterInterval != null) { currentIterator = Iterators.filter(currentIterator, v -> { - BreakendSummary bs = v.getBreakendSummary(); - return bs.start >= filterInterval.start && bs.start <= filterInterval.end; + BreakpointSummary bs = v.getBreakendSummary(); + return (bs.referenceIndex == filterInterval.referenceIndex && bs.start >= filterInterval.start && bs.start <= filterInterval.end) || + (bs.referenceIndex2 == filterInterval.referenceIndex && bs.start2 >= filterInterval.start && bs.start2 <= filterInterval.end); }); } } @@ -84,7 +85,7 @@ public boolean hasNext() { return true; } @Override - public VariantContextDirectedEvidence next() { + public VariantContextDirectedBreakpoint next() { if (!hasNext()) throw new NoSuchElementException(); return currentIterator.next(); } diff --git a/src/main/java/au/edu/wehi/idsv/VariantCaller.java b/src/main/java/au/edu/wehi/idsv/VariantCaller.java index e0d79be3a..bcc6a74d2 100644 --- a/src/main/java/au/edu/wehi/idsv/VariantCaller.java +++ b/src/main/java/au/edu/wehi/idsv/VariantCaller.java @@ -95,9 +95,9 @@ private void callChunk(File output, AggregateEvidenceSource es, int chunkNumber, try (VariantCallIterator rawit = new VariantCallIterator(es, chunck, chunkNumber)) { try (VariantContextWriter vcfWriter = processContext.getVariantContextWriter(tmp, false)) { log.info("Start ", msg); - try (AsyncBufferedIterator it = new AsyncBufferedIterator<>(rawit, "VariantCaller " + chunkMsg)) { + try (AsyncBufferedIterator it = new AsyncBufferedIterator<>(rawit, "VariantCaller " + chunkMsg)) { while (it.hasNext()) { - VariantContextDirectedEvidence loc = it.next(); + VariantContextDirectedBreakpoint loc = it.next(); if (loc.getBreakendQual() >= processContext.getVariantCallingParameters().minScore || processContext.getVariantCallingParameters().writeFiltered) { // If we're under min score with all possible evidence allocated, we're definitely going to fail // when we restrict evidence to single breakpoint support diff --git a/src/main/java/au/edu/wehi/idsv/VariantContextDirectedBreakpoint.java b/src/main/java/au/edu/wehi/idsv/VariantContextDirectedBreakpoint.java index 9c4fe4b46..44c67fd18 100644 --- a/src/main/java/au/edu/wehi/idsv/VariantContextDirectedBreakpoint.java +++ b/src/main/java/au/edu/wehi/idsv/VariantContextDirectedBreakpoint.java @@ -141,6 +141,6 @@ public DirectedBreakpoint asRemote() { } @Override public String getRemoteEvidenceID() { - throw new NotImplementedException("Not required by GRIDSS"); + return getAttributeAsString(VcfSvConstants.PARTNER_BREAKEND_ID_KEY, null); } } diff --git a/src/test/java/au/edu/wehi/idsv/VariantCallIteratorTest.java b/src/test/java/au/edu/wehi/idsv/VariantCallIteratorTest.java index fb15b74ad..f6d95405d 100644 --- a/src/test/java/au/edu/wehi/idsv/VariantCallIteratorTest.java +++ b/src/test/java/au/edu/wehi/idsv/VariantCallIteratorTest.java @@ -8,9 +8,12 @@ import org.junit.Test; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -public class VariantCallIteratorTest extends TestHelper { +import htsjdk.samtools.QueryInterval; + +public class VariantCallIteratorTest extends IntermediateFilesTest { @Test public void margin_should_expand_and_contract_past_chromosome_end() throws InterruptedException { List list = new ArrayList(); @@ -70,4 +73,17 @@ public void should_call_orientations() throws InterruptedException { List result = Lists.newArrayList(ecp); assertEquals(4 * 2, result.size()); } + @Test + public void interval_caller_should_filter_calls_in_which_neither_breakend_starts_in_interval() throws InterruptedException { + createInput( + RP(0, 1, 2, 1), + DP(0, 1, "1M", true, 1, 100, "1M", false)); + SAMEvidenceSource ses = new SAMEvidenceSource(getCommandlineContext(), input, null, 0); + VariantCallIterator ecp = new VariantCallIterator( + new AggregateEvidenceSource(getCommandlineContext(), ImmutableList.of(ses), null), + new QueryInterval(0, 1, 10), + 0); + List result = Lists.newArrayList(ecp); + assertEquals(2, result.size()); + } } diff --git a/src/test/java/gridss/AllocateEvidenceTest.java b/src/test/java/gridss/AllocateEvidenceTest.java index fade7e310..f4e5c7007 100644 --- a/src/test/java/gridss/AllocateEvidenceTest.java +++ b/src/test/java/gridss/AllocateEvidenceTest.java @@ -8,9 +8,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; import org.junit.Test; @@ -35,6 +37,11 @@ import htsjdk.samtools.SAMRecord; public class AllocateEvidenceTest extends IntermediateFilesTest { + private void assertSymmetrical(List breakpoints) { + Set evidenceId = breakpoints.stream().map(bp -> bp.getEvidenceID()).collect(Collectors.toSet()); + Set remoteEvidenceId = breakpoints.stream().map(bp -> bp.getRemoteEvidenceID()).collect(Collectors.toSet()); + assertEquals(evidenceId, remoteEvidenceId); + } @Test public void should_annotate_reads() throws IOException { final ProcessingContext pc = getCommandlineContext(); @@ -60,7 +67,9 @@ public void should_annotate_reads() throws IOException { cmd.OUTPUT_VCF = new File(testFolder.getRoot(), "annotated.vcf"); List vcfs = Lists.newArrayList(Iterables.filter(getVcf(output, null), VariantContextDirectedBreakpoint.class)); assertEquals(2 * 1, vcfs.size()); // both breakends + assertSymmetrical(vcfs); List results = Lists.newArrayList(cmd.iterator(new AutoClosingIterator<>(vcfs.iterator()), MoreExecutors.newDirectExecutorService())); + assertSymmetrical(results); assertEquals(vcfs.size(), results.size()); VariantContextDirectedBreakpoint e = results.get(0); assertEquals(2, e.getBreakpointEvidenceCount()); @@ -90,7 +99,9 @@ public void should_apply_filters() throws IOException { cmd.OUTPUT_VCF = new File(testFolder.getRoot(), "annotated.vcf"); List vcfs = Lists.newArrayList(Iterables.filter(getVcf(output, null), VariantContextDirectedBreakpoint.class)); assertEquals(2 * 1, vcfs.size()); // both breakends + assertSymmetrical(vcfs); List results = Lists.newArrayList(cmd.iterator(new AutoClosingIterator<>(vcfs.iterator()), MoreExecutors.newDirectExecutorService())); + assertSymmetrical(results); // single read support assertEquals(0, results.size()); } @@ -133,7 +144,9 @@ public void should_uniquely_assign() throws IOException, InterruptedException, E //List annotated = getVcf(new File(testFolder.getRoot(), "out.vcf"), null); List rawcalls = getVcf(output, null); - List calls = getVcf(cmd.OUTPUT_VCF, null); + List calls = getVcf(cmd.OUTPUT_VCF, null); + assertSymmetrical(rawcalls.stream().map(x -> (VariantContextDirectedBreakpoint)x).collect(Collectors.toList())); + assertSymmetrical(calls.stream().map(x -> (VariantContextDirectedBreakpoint)x).collect(Collectors.toList())); // with no filtering, annotation should not change call set double expectedEvidence = 0; for (DirectedEvidence e : ses.evidence) {