package picard.vcf; import htsjdk.samtools.util.IOUtil; import htsjdk.variant.variantcontext.*; import htsjdk.variant.vcf.VCFFileReader; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import picard.cmdline.CommandLineProgramTest; import java.io.File; import java.util.*; /** * Test class for LiftoverVcf. * * Created by ebanks on 8/11/15. */ public class LiftoverVcfTest extends CommandLineProgramTest { private static final File TEST_DATA_PATH = new File("testdata/picard/vcf/"); private static final File CHAIN_FILE = new File(TEST_DATA_PATH, "test.over.chain"); private static final File CHAIN_FILE_WITH_BAD_CONTIG = new File(TEST_DATA_PATH, "test.over.badContig.chain"); private static final File REFERENCE_FILE = new File(TEST_DATA_PATH, "dummy.reference.fasta"); private static final File OUTPUT_DATA_PATH = IOUtil.createTempDir("LiftoverVcfsTest", null); public String getCommandLineProgramName() { return LiftoverVcf.class.getSimpleName(); } @AfterClass public void teardown() { IOUtil.deleteDirectoryTree(OUTPUT_DATA_PATH); } @Test public void testDoNotFixReverseComplementedIndels() { final File liftOutputFile = new File(OUTPUT_DATA_PATH, "lift-delete-me.vcf"); final File rejectOutputFile = new File(OUTPUT_DATA_PATH, "reject-delete-me.vcf"); final File input = new File(TEST_DATA_PATH, "testLiftover.vcf"); liftOutputFile.deleteOnExit(); rejectOutputFile.deleteOnExit(); final String[] args = new String[]{ "INPUT=" + input.getAbsolutePath(), "OUTPUT=" + liftOutputFile.getAbsolutePath(), "REJECT=" + rejectOutputFile.getAbsolutePath(), "CHAIN=" + CHAIN_FILE, "REFERENCE_SEQUENCE=" + REFERENCE_FILE, "CREATE_INDEX=false" }; Assert.assertEquals(runPicardCommandLine(args), 0); final VCFFileReader liftReader = new VCFFileReader(liftOutputFile, false); for (final VariantContext inputContext : liftReader) { Assert.fail("there should be no passing indels in the liftover"); } final VCFFileReader rejectReader = new VCFFileReader(rejectOutputFile, false); int counter = 0; for (final VariantContext inputContext : rejectReader) { counter++; } Assert.assertEquals(counter, 2, "the wrong number of rejected indels failed the liftover"); } @Test public void testFixReverseComplementedGenotypes() { final Allele refA = Allele.create("A", true); final Allele altC = Allele.create("C", false); final GenotypesContext originalGenotypes = GenotypesContext.create(3); originalGenotypes.add(new GenotypeBuilder("homref").alleles(Arrays.asList(refA, refA)).make()); originalGenotypes.add(new GenotypeBuilder("het").alleles(Arrays.asList(refA, altC)).make()); originalGenotypes.add(new GenotypeBuilder("homvar").alleles(Arrays.asList(altC, altC)).make()); final Allele refT = Allele.create("T", true); final Allele altG = Allele.create("G", false); final GenotypesContext expectedGenotypes = GenotypesContext.create(3); expectedGenotypes.add(new GenotypeBuilder("homref").alleles(Arrays.asList(refT, refT)).make()); expectedGenotypes.add(new GenotypeBuilder("het").alleles(Arrays.asList(refT, altG)).make()); expectedGenotypes.add(new GenotypeBuilder("homvar").alleles(Arrays.asList(altG, altG)).make()); final Map<Allele, Allele> reverseComplementAlleleMap = new HashMap<Allele, Allele>(2); reverseComplementAlleleMap.put(refA, refT); reverseComplementAlleleMap.put(altC, altG); final GenotypesContext actualGenotypes = LiftoverVcf.fixGenotypes(originalGenotypes, reverseComplementAlleleMap); for ( final String sample : Arrays.asList("homref", "het", "homvar") ) { final List<Allele> expected = expectedGenotypes.get(sample).getAlleles(); final List<Allele> actual = actualGenotypes.get(sample).getAlleles(); Assert.assertEquals(expected.get(0), actual.get(0)); Assert.assertEquals(expected.get(1), actual.get(1)); } } @DataProvider(name = "dataTestMissingContigInReference") public Object[][] dataTestHaplotypeProbabilitiesFromSequenceAddToProbs() { return new Object[][]{ {false, LiftoverVcf.EXIT_CODE_WHEN_CONTIG_NOT_IN_REFERENCE}, {true, 0} }; } @Test(dataProvider = "dataTestMissingContigInReference") public void testMissingContigInReference(boolean warnOnMissingContext, int expectedReturnCode) { final File liftOutputFile = new File(OUTPUT_DATA_PATH, "lift-delete-me.vcf"); final File rejectOutputFile = new File(OUTPUT_DATA_PATH, "reject-delete-me.vcf"); final File input = new File(TEST_DATA_PATH, "testLiftoverUsingMissingContig.vcf"); liftOutputFile.deleteOnExit(); rejectOutputFile.deleteOnExit(); // Test using WMC option final String[] argsWithWarnOnMissingContig = new String[]{ "INPUT=" + input.getAbsolutePath(), "OUTPUT=" + liftOutputFile.getAbsolutePath(), "REJECT=" + rejectOutputFile.getAbsolutePath(), "CHAIN=" + CHAIN_FILE_WITH_BAD_CONTIG, "REFERENCE_SEQUENCE=" + REFERENCE_FILE, "CREATE_INDEX=false", "WMC=" + warnOnMissingContext }; Assert.assertEquals(runPicardCommandLine(argsWithWarnOnMissingContig), expectedReturnCode); } @DataProvider(name = "dataTestWriteOriginalPosition") public Object[][] dataTestWriteOriginalPosition() { return new Object[][]{ {false}, {true} }; } @Test(dataProvider = "dataTestWriteOriginalPosition") public void testWriteOriginalPosition(boolean shouldWriteOriginalPosition) { final File liftOutputFile = new File(OUTPUT_DATA_PATH, "lift-delete-me.vcf"); final File rejectOutputFile = new File(OUTPUT_DATA_PATH, "reject-delete-me.vcf"); final File input = new File(TEST_DATA_PATH, "testLiftover.vcf"); liftOutputFile.deleteOnExit(); rejectOutputFile.deleteOnExit(); final String[] args = new String[]{ "INPUT=" + input.getAbsolutePath(), "OUTPUT=" + liftOutputFile.getAbsolutePath(), "REJECT=" + rejectOutputFile.getAbsolutePath(), "CHAIN=" + CHAIN_FILE, "REFERENCE_SEQUENCE=" + REFERENCE_FILE, "CREATE_INDEX=false", "WRITE_ORIGINAL_POSITION=" + shouldWriteOriginalPosition }; runPicardCommandLine(args); try (VCFFileReader liftReader = new VCFFileReader(liftOutputFile, false)) { for (VariantContext vc : liftReader) { if (shouldWriteOriginalPosition) { Assert.assertNotNull(vc.getAttribute(LiftoverVcf.ORIGINAL_CONTIG)); Assert.assertNotNull(vc.getAttribute(LiftoverVcf.ORIGINAL_START)); } else { Assert.assertFalse(vc.hasAttribute(LiftoverVcf.ORIGINAL_CONTIG)); Assert.assertFalse(vc.hasAttribute(LiftoverVcf.ORIGINAL_START)); } } } } }