diff --git a/src/main/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/AssemblyBasedCallerUtils.java b/src/main/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/AssemblyBasedCallerUtils.java index 5c488464bb1..c02f5bde71b 100644 --- a/src/main/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/AssemblyBasedCallerUtils.java +++ b/src/main/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/AssemblyBasedCallerUtils.java @@ -132,7 +132,6 @@ public static void finalizeRegion(final AssemblyRegion region, if ( region.isFinalized() ) { return; } - final byte minTailQualityToUse = errorCorrectReads ? HaplotypeCallerEngine.MIN_TAIL_QUALITY_WITH_ERROR_CORRECTION : minTailQuality; final List readsToUse = new ArrayList<>(); diff --git a/src/main/java/org/broadinstitute/hellbender/utils/NGSPlatform.java b/src/main/java/org/broadinstitute/hellbender/utils/NGSPlatform.java index 32b92bd1489..68e4205c1eb 100644 --- a/src/main/java/org/broadinstitute/hellbender/utils/NGSPlatform.java +++ b/src/main/java/org/broadinstitute/hellbender/utils/NGSPlatform.java @@ -24,8 +24,10 @@ public enum NGSPlatform { ION_TORRENT(SequencerFlowClass.FLOW, "IONTORRENT"), CAPILLARY(SequencerFlowClass.OTHER, "CAPILLARY"), HELICOS(SequencerFlowClass.OTHER, "HELICOS"), + ULTIMA(SequencerFlowClass.FLOW, "ULTIMA"), UNKNOWN(SequencerFlowClass.OTHER, "UNKNOWN"); + /** * Array of the prefix names in a BAM file for each of the platforms. */ diff --git a/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedRead.java b/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedRead.java index 39102aecc55..4e2283040a4 100644 --- a/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedRead.java +++ b/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedRead.java @@ -201,7 +201,7 @@ public FlowBasedRead(final GATKRead read, final String flowOrder, final int maxH public FlowBasedRead(final SAMRecord samRecord, final String flowOrder, final int maxHmer, final FlowBasedArgumentCollection fbargs) { super(samRecord); Utils.nonNull(fbargs); - Utils.validate(FlowBasedReadUtils.isFlow(samRecord), "FlowBasedRead can only be used on flow reads. failing read: " + samRecord); + Utils.validate(FlowBasedReadUtils.hasFlowTags(samRecord), "FlowBasedRead can only be used on flow reads. failing read: " + samRecord); this.fbargs = fbargs; this.maxHmer = maxHmer; this.samRecord = samRecord; @@ -352,7 +352,7 @@ private void parseSingleHmer(final double[] probs, final byte[] tp, final int fl if (flowMatrix[loc][flowIdx] == fbargs.fillingValue) { flowMatrix[loc][flowIdx] = probs[i]; } else { - flowMatrix[loc][flowIdx] += probs[i]; + flowMatrix[loc][flowIdx] += probs[i]; } } } diff --git a/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtils.java b/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtils.java index 63bb6410540..d7a7a76faaf 100644 --- a/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtils.java +++ b/src/main/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtils.java @@ -1,5 +1,6 @@ package org.broadinstitute.hellbender.utils.read; +import gov.nih.nlm.ncbi.ngs.NGS; import htsjdk.samtools.SAMFileHeader; import htsjdk.samtools.SAMReadGroupRecord; import htsjdk.samtools.SAMRecord; @@ -7,13 +8,22 @@ import org.broadinstitute.hellbender.cmdline.argumentcollections.MarkDuplicatesSparkArgumentCollection; import org.broadinstitute.hellbender.exceptions.GATKException; import org.broadinstitute.hellbender.tools.FlowBasedArgumentCollection; +import org.broadinstitute.hellbender.utils.NGSPlatform; +import org.broadinstitute.hellbender.utils.SequencerFlowClass; import org.broadinstitute.hellbender.utils.Utils; import java.util.LinkedHashMap; import java.util.Map; + /** - * utility class for flow based read + * Utility class for working with flow-based reads + * + * The main member static class is {@code ReadGroupInfo} that contains methods that allow + * working with headers of flow based reads and extracting the flow order and the maximal hmer class called. + * It also contains methods to check how the read was clipped ({@code readEndMarkedUnclipped}, {@code readEndMarkedUncertain}) + * Lastly, {@code FlowBasedReadUtils.isFlowPlatform} is **the** function to determine if the data are flow-based + * */ public class FlowBasedReadUtils { @@ -26,17 +36,35 @@ public class FlowBasedReadUtils { static public class ReadGroupInfo { final public String flowOrder; final public int maxClass; - + final public boolean isFlowPlatform; private String reversedFlowOrder = null; public ReadGroupInfo(final SAMReadGroupRecord readGroup) { + if (readGroup.getPlatform()==null){ + isFlowPlatform = false; + } else if (NGSPlatform.fromReadGroupPL(readGroup.getPlatform())==NGSPlatform.UNKNOWN){ + isFlowPlatform = false; + } else if (NGSPlatform.fromReadGroupPL(readGroup.getPlatform()) == NGSPlatform.LS454) { + //old Ultima data can have PLATFORM==LS454 and not have FO tag + isFlowPlatform = true; + } else if (NGSPlatform.fromReadGroupPL(readGroup.getPlatform()) == NGSPlatform.ULTIMA){ + if (readGroup.getFlowOrder()!=null) { + isFlowPlatform = true; + } else { + throw new RuntimeException("Malformed Ultima read group identified, aborting: " + readGroup); + } + } else { + isFlowPlatform = false; + } - Utils.nonNull(readGroup); - this.flowOrder = readGroup.getFlowOrder(); - Utils.nonNull(this.flowOrder); - - String mc = readGroup.getAttribute(FlowBasedRead.MAX_CLASS_READ_GROUP_TAG); - this.maxClass = (mc == null) ? FlowBasedRead.MAX_CLASS : Integer.parseInt(mc); + if (isFlowPlatform) { + this.flowOrder = readGroup.getFlowOrder(); + String mc = readGroup.getAttribute(FlowBasedRead.MAX_CLASS_READ_GROUP_TAG); + this.maxClass = (mc == null) ? FlowBasedRead.MAX_CLASS : Integer.parseInt(mc); + } else { // not a flow platform + this.flowOrder = null; + this.maxClass = 0; + } } public synchronized String getReversedFlowOrder() { @@ -45,6 +73,7 @@ public synchronized String getReversedFlowOrder() { } return reversedFlowOrder; } + } public static boolean readEndMarkedUncertain(final GATKRead rec) { @@ -118,22 +147,36 @@ public static int flowSumOfBaseQualities(final GATKRead read) { } } - public static boolean isFlow(final GATKRead rec) { + public static boolean hasFlowTags(final GATKRead rec) { return rec.hasAttribute(FlowBasedRead.FLOW_MATRIX_TAG_NAME) || rec.hasAttribute(FlowBasedRead.FLOW_MATRiX_OLD_TAG_KR) || rec.hasAttribute(FlowBasedRead.FLOW_MATRiX_OLD_TAG_TI); } - public static boolean isFlow(final SAMRecord rec) { + public static boolean hasFlowTags(final SAMRecord rec) { return rec.hasAttribute(FlowBasedRead.FLOW_MATRIX_TAG_NAME) || rec.hasAttribute(FlowBasedRead.FLOW_MATRiX_OLD_TAG_KR) || rec.hasAttribute(FlowBasedRead.FLOW_MATRiX_OLD_TAG_TI); } + /** + * + * This is the function to run if you want to ask if the data are flow-based + * + * @param hdr - file header + * @param read - the read + * @return true if the read is flow-based + */ + public static boolean isFlowPlatform(final SAMFileHeader hdr, final GATKRead read) { + if (!hasFlowTags(read)){ + return false; + } + return getReadGroupInfo(hdr, read).isFlowPlatform; + } public static synchronized ReadGroupInfo getReadGroupInfo(final SAMFileHeader hdr, final GATKRead read) { - if ( !isFlow(read) ) { + if ( !hasFlowTags(read) ) { throw new IllegalArgumentException("read must be flow based: " + read); } diff --git a/src/main/java/org/broadinstitute/hellbender/utils/read/markduplicates/sparkrecords/FlowModeFragment.java b/src/main/java/org/broadinstitute/hellbender/utils/read/markduplicates/sparkrecords/FlowModeFragment.java index 45109e04ee5..f27df7e367a 100644 --- a/src/main/java/org/broadinstitute/hellbender/utils/read/markduplicates/sparkrecords/FlowModeFragment.java +++ b/src/main/java/org/broadinstitute/hellbender/utils/read/markduplicates/sparkrecords/FlowModeFragment.java @@ -45,7 +45,7 @@ public FlowModeFragment(final GATKRead first, final SAMFileHeader header, int pa headerLibraryMap.get(MarkDuplicatesSparkUtils.getLibraryForRead(first, header, LibraryIdGenerator.UNKNOWN_LIBRARY))); this.score = (this.end != FlowBasedReadUtils.FLOW_BASED_INSIGNIFICANT_END) - ? ((mdArgs.FLOW_QUALITY_SUM_STRATEGY && FlowBasedReadUtils.isFlow(first)) ? computeFlowDuplicateScore(first, start, end) : scoringStrategy.score(first)) + ? ((mdArgs.FLOW_QUALITY_SUM_STRATEGY && FlowBasedReadUtils.hasFlowTags(first)) ? computeFlowDuplicateScore(first, start, end) : scoringStrategy.score(first)) : -1; } diff --git a/src/test/java/org/broadinstitute/hellbender/GATKBaseTest.java b/src/test/java/org/broadinstitute/hellbender/GATKBaseTest.java index 1abba24fefc..d93f28f22c0 100644 --- a/src/test/java/org/broadinstitute/hellbender/GATKBaseTest.java +++ b/src/test/java/org/broadinstitute/hellbender/GATKBaseTest.java @@ -71,7 +71,9 @@ public abstract class GATKBaseTest extends BaseTest { // ~600,000 reads from chromosomes 20 and 21 of an NA12878 WGS bam aligned to b37, plus ~50,000 unmapped reads public static final String NA12878_20_21_WGS_bam = largeFileTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.20.21.bam"; + public static final String NA12878_20_21_WGS_mmp2_bam = largeFileTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam"; public static final String NA12878_20_21_WGS_cram = largeFileTestDir + "CEUTrio.HiSeq.WGS.b37.NA12878.20.21.cram"; + public static final String NA12878_20_21_covered_regions = publicTestDir + "wgs_calling_regions.v1.chr20_chr21.interval_list"; // ~10,000 reads from chromosome 20 of NA12878 RNA-seq, aligned to b37 with STAR diff --git a/src/test/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java b/src/test/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java index 2d3eb1a94f5..54585b1709d 100644 --- a/src/test/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java +++ b/src/test/java/org/broadinstitute/hellbender/tools/walkers/haplotypecaller/HaplotypeCallerIntegrationTest.java @@ -101,7 +101,38 @@ public void testVCFModeIsConsistentWithPastResults(final String inputFileName, f IntegrationTestSpec.assertEqualTextFiles(output, expected); } } - + + /* + * Test that minimap2 data are supported and consistent with past results + */ + @Test + public void testVCFModeMinimap2IsConsistentWithPastResults() throws Exception { + final String inputFileName = NA12878_20_21_WGS_mmp2_bam; + final String referenceFileName = b37_reference_20_21; + Utils.resetRandomGenerator(); + + final File output = createTempFile("testVCFModeIsConsistentWithPastResults", ".vcf"); + final File expected = new File(TEST_FILES_DIR, "expected.testVCFMode.mmp2.gatk4.vcf"); + + final String outputPath = UPDATE_EXACT_MATCH_EXPECTED_OUTPUTS ? expected.getAbsolutePath() : output.getAbsolutePath(); + + final String[] args = { + "-I", inputFileName, + "-R", referenceFileName, + "-L", "20:10000000-10100000", + "-O", outputPath, + "-pairHMM", "AVX_LOGLESS_CACHING", + "--" + StandardArgumentDefinitions.ADD_OUTPUT_VCF_COMMANDLINE, "false" + }; + + runCommandLine(args); + + // Test for an exact match against past results + if ( ! UPDATE_EXACT_MATCH_EXPECTED_OUTPUTS ) { + IntegrationTestSpec.assertEqualTextFiles(output, expected); + } + } + /* * Test that in JunctionTree mode we're consistent with past JunctionTree results (over non-complicated data) */ diff --git a/src/test/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtilsUnitTest.java b/src/test/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtilsUnitTest.java index 91078d386aa..b249b21461b 100644 --- a/src/test/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtilsUnitTest.java +++ b/src/test/java/org/broadinstitute/hellbender/utils/read/FlowBasedReadUtilsUnitTest.java @@ -1,19 +1,21 @@ package org.broadinstitute.hellbender.utils.read; -import htsjdk.samtools.SAMFileHeader; -import htsjdk.samtools.SAMReadGroupRecord; -import htsjdk.samtools.SamReader; -import htsjdk.samtools.SamReaderFactory; +import htsjdk.samtools.*; import org.broadinstitute.hellbender.GATKBaseTest; +import org.broadinstitute.hellbender.tools.FlowBasedArgumentCollection; +import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; public class FlowBasedReadUtilsUnitTest extends GATKBaseTest{ @Test - void testReadGroupParsing() throws Exception{ + void testReadGroupParsing(){ final String testResourceDir = publicTestDir + "org/broadinstitute/hellbender/utils/read/flow/reads/"; final String inputDir = testResourceDir + "/input/"; @@ -24,9 +26,116 @@ void testReadGroupParsing() throws Exception{ FlowBasedReadUtils.ReadGroupInfo frg1 = new FlowBasedReadUtils.ReadGroupInfo(rg1); assert(frg1.maxClass==12); assert(frg1.flowOrder.startsWith("TGCA")); + assert(frg1.flowOrder.startsWith("TGCA")); + assert(frg1.isFlowPlatform); + SAMReadGroupRecord rg2 = header.getReadGroup("UGAv3-73"); FlowBasedReadUtils.ReadGroupInfo frg2 = new FlowBasedReadUtils.ReadGroupInfo(rg2); assert(frg2.maxClass==20); assert(frg2.flowOrder.startsWith("TGCA")); + assert(frg2.isFlowPlatform); + SAMReadGroupRecord rg3 = header.getReadGroup("UGAv3-74"); + FlowBasedReadUtils.ReadGroupInfo frg3 = new FlowBasedReadUtils.ReadGroupInfo(rg3); + assert(!frg3.isFlowPlatform); + + } + + //testing that an occasional read with tp (but not ULTIMA) does not get identified as flow-based. + // Here the read group is: + // @RG ID:test SM:HG001 PL:ILLUMINA + // but the reads have tp because they were aligned with minimap2: + // 20FUKAAXX100202:5:43:9081:11499/2 272 chr14_GL000009v2_random 156269 ... tp:A:S cm:i:12 s1:i:87 de:f:0.0099 rl:i:0 + @Test + void testNonFlowReadGroupParsing(){ + final String testResourceDir = publicTestDir + "org/broadinstitute/hellbender/utils/read/flow/reads/"; + final String inputDir = testResourceDir + "/input/"; + + final Path inputFile = FileSystems.getDefault().getPath(inputDir, "non_flow_reads_with_tp.bam"); + final SamReader reader = SamReaderFactory.makeDefault().open(new File(inputFile.toString())); + SAMFileHeader header = reader.getFileHeader(); + SAMRecord read = reader.iterator().next(); + GATKRead gread = new SAMRecordToGATKReadAdapter(read); + assert(FlowBasedReadUtils.hasFlowTags(gread)); + FlowBasedReadUtils.ReadGroupInfo frg1 = FlowBasedReadUtils.getReadGroupInfo(header, gread); + assert(!frg1.isFlowPlatform); + } + + private GATKRead makeRead(final byte[] bases, final boolean isReverse) { + + byte[] quals = new byte[bases.length]; + + final String cigar = String.format("%dM", bases.length); + GATKRead read = ArtificialReadUtils.createArtificialRead(bases, quals, cigar); + read.setPosition("chr1",100); + read.setIsReverseStrand(isReverse); + return read; } + + @DataProvider(name="isFlowPlatform") + Object[][] getIsFlowPlatformInputs() { + List tests = new ArrayList<>(); + SAMFileHeader hdr = new SAMFileHeader(); + + GATKRead read1 = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + SAMReadGroupRecord rg1 = new SAMReadGroupRecord("rg1"); + rg1.setPlatform("ILLUMINA"); + read1.setReadGroup("rg1"); + hdr.addReadGroup(rg1); + tests.add(new Object[]{hdr, read1, false}); + + GATKRead read2 = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + read2.setAttribute("tp","blabla"); + SAMReadGroupRecord rg2 = new SAMReadGroupRecord("rg2"); + rg2.setPlatform("ILLUMINA"); + read2.setReadGroup("rg2"); + hdr.addReadGroup(rg2); + tests.add(new Object[]{hdr, read2, false}); + + GATKRead read3 = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + read3.setAttribute("tp",new byte[6]); + SAMReadGroupRecord rg3 = new SAMReadGroupRecord("rg3"); + rg3.setPlatform("LS454"); + read3.setReadGroup("rg3"); + hdr.addReadGroup(rg3); + tests.add(new Object[]{hdr, read3, true}); + + GATKRead read4 = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + read4.setAttribute("tp",new byte[6]); + SAMReadGroupRecord rg4 = new SAMReadGroupRecord("rg4"); + rg4.setPlatform("ULTIMA"); + rg4.setAttribute("FO","TGCATGCA"); + read4.setReadGroup("rg4"); + hdr.addReadGroup(rg4); + tests.add(new Object[]{hdr, read4, true}); + + GATKRead read5 = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + read5.setAttribute("tp",new byte[6]); + SAMReadGroupRecord rg5 = new SAMReadGroupRecord("rg5"); + rg5.setPlatform("LS454"); + rg5.setAttribute("FO","TGCATGCA"); + read5.setReadGroup("rg5"); + hdr.addReadGroup(rg5); + tests.add(new Object[]{hdr, read5, true}); + + + return tests.toArray(new Object[][]{}); + } + + @Test (dataProvider = "isFlowPlatform") + void testIsFlowPlatform(final SAMFileHeader hdr, final GATKRead read, final boolean answer){ + assert(FlowBasedReadUtils.isFlowPlatform(hdr, read) == answer); + } + + @Test(expectedExceptions = {RuntimeException.class}) + void testMalformedUltimaRGThrowsException(){ + GATKRead read = makeRead(new byte[]{'T','A','G','C','G','A'}, false); + read.setAttribute("tp",new byte[6]); + SAMReadGroupRecord rg = new SAMReadGroupRecord("rg"); + rg.setPlatform("ULTIMA"); + read.setReadGroup("rg"); + SAMFileHeader hdr = new SAMFileHeader(); + hdr.addReadGroup(rg); + FlowBasedReadUtils.isFlowPlatform(hdr, read); + } + } diff --git a/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam b/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam new file mode 100644 index 00000000000..8485260555b --- /dev/null +++ b/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fabab864097f4684ec753008bf583523d43778b8236c82dfe3732bd0f3feda3f +size 5514698 diff --git a/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam.bai b/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam.bai new file mode 100644 index 00000000000..dd02c9e8027 --- /dev/null +++ b/src/test/resources/large/CEUTrio.HiSeq.WGS.b37.NA12878.20.21.mmp2.bam.bai @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23fa02d9dcfe056b958a738e8b3e80a510edc0d4a83f1f31cd868428a40d531c +size 75936 diff --git a/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf b/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf new file mode 100644 index 00000000000..9fd5ecdc89e --- /dev/null +++ b/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf @@ -0,0 +1,46 @@ +##fileformat=VCFv4.2 +##FILTER= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##contig= +##contig= +#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT NA12878 +20 10001298 . T A 107.84 . AC=2;AF=1.00;AN=2;DP=3;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=57.46;QD=25.36;SOR=1.179 GT:AD:DP:GQ:PL 1/1:0,3:3:9:121,9,0 +20 10001436 . A AAGGCT 706.03 . AC=2;AF=1.00;AN=2;DP=16;ExcessHet=0.0000;FS=0.000;MLEAC=2;MLEAF=1.00;MQ=60.00;QD=28.73;SOR=5.670 GT:AD:DP:GQ:PL 1/1:0,16:16:48:720,48,0 +20 10001474 . C T 367.06 . AC=2;AF=1.00;AN=2;DP=10;ExcessHet=0.0000;FS=0.000;MLEAC=2;MLEAF=1.00;MQ=60.00;QD=30.97;SOR=4.804 GT:AD:DP:GQ:PL 1/1:0,10:10:30:381,30,0 +20 10001628 . G A 34.48 . AC=2;AF=1.00;AN=2;DP=1;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=34.48;SOR=1.609 GT:AD:DP:GQ:PL 1/1:0,1:1:3:44,3,0 +20 10003651 . T C 70.84 . AC=2;AF=1.00;AN=2;DP=3;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=50.61;QD=23.61;SOR=1.179 GT:AD:DP:GQ:PL 1/1:0,3:3:9:84,9,0 +20 10003692 . A G 75.84 . AC=2;AF=1.00;AN=2;DP=3;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=25.28;SOR=1.179 GT:AD:DP:GQ:PL 1/1:0,3:3:9:89,9,0 +20 10003832 . G A 70.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=27.24;SOR=0.693 GT:AD:DP:GQ:PL 1/1:0,2:2:6:82,6,0 +20 10004094 . A C 108.84 . AC=2;AF=1.00;AN=2;DP=3;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=59.67;QD=28.20;SOR=1.179 GT:AD:DP:GQ:PL 1/1:0,3:3:9:122,9,0 +20 10004610 . A C 33.48 . AC=2;AF=1.00;AN=2;DP=1;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=33.48;SOR=1.609 GT:AD:DP:GQ:PL 1/1:0,1:1:3:43,3,0 +20 10009246 . A G 33.48 . AC=2;AF=1.00;AN=2;DP=1;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=33.48;SOR=1.609 GT:AD:DP:GQ:PL 1/1:0,1:1:3:43,3,0 +20 10009719 . A G 100.84 . AC=2;AF=1.00;AN=2;DP=3;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=58.38;QD=33.61;SOR=2.833 GT:AD:DP:GQ:PL 1/1:0,3:3:9:114,9,0 +20 10010832 . T C 67.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=33.66;SOR=0.693 GT:AD:DP:GQ:PL 1/1:0,2:2:6:79,6,0 +20 10012570 . G GCA 35.44 . AC=2;AF=1.00;AN=2;DP=1;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=25.00;SOR=1.609 GT:AD:DP:GQ:PL 1/1:0,1:1:3:45,3,0 +20 10012572 . GT G 35.44 . AC=2;AF=1.00;AN=2;DP=1;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=29.56;SOR=1.609 GT:AD:DP:GQ:PL 1/1:0,1:1:3:45,3,0 +20 10026357 . T C 67.64 . AC=1;AF=0.500;AN=2;BaseQRankSum=0.967;DP=3;ExcessHet=0.0000;FS=4.771;MLEAC=1;MLEAF=0.500;MQ=60.00;MQRankSum=0.000;QD=22.55;ReadPosRankSum=0.000;SOR=2.225 GT:AD:DP:GQ:PL 0/1:1,2:3:21:75,0,21 +20 10032413 . T G 53.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=26.66;SOR=2.303 GT:AD:DP:GQ:PL 1/1:0,2:2:6:65,6,0 +20 10041304 . C T 65.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=32.66;SOR=0.693 GT:AD:DP:GQ:PL 1/1:0,2:2:6:77,6,0 +20 10042319 . C T 74.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=30.62;SOR=2.303 GT:AD:DP:GQ:PL 1/1:0,2:2:6:86,6,0 +20 10071187 . G A 66.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=33.16;SOR=2.303 GT:AD:DP:GQ:PL 1/1:0,2:2:6:78,6,0 +20 10074240 . T C 69.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=48.76;QD=34.66;SOR=0.693 GT:AD:DP:GQ:PL 1/1:0,2:2:6:81,6,0 +20 10088063 . C T 64.32 . AC=2;AF=1.00;AN=2;DP=2;ExcessHet=0.0000;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=60.00;QD=32.16;SOR=2.303 GT:AD:DP:GQ:PL 1/1:0,2:2:6:76,6,0 diff --git a/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf.idx b/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf.idx new file mode 100644 index 00000000000..061ac7ed0c4 Binary files /dev/null and b/src/test/resources/org/broadinstitute/hellbender/tools/haplotypecaller/expected.testVCFMode.mmp2.gatk4.vcf.idx differ diff --git a/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/non_flow_reads_with_tp.bam b/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/non_flow_reads_with_tp.bam new file mode 100644 index 00000000000..deada3e38f0 Binary files /dev/null and b/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/non_flow_reads_with_tp.bam differ diff --git a/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/sample_mc.bam b/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/sample_mc.bam index 1082627aeb3..64c5f94fc77 100644 Binary files a/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/sample_mc.bam and b/src/test/resources/org/broadinstitute/hellbender/utils/read/flow/reads/input/sample_mc.bam differ