package picard.analysis.artifacts;
import htsjdk.samtools.metrics.MetricsFile;
import htsjdk.samtools.util.IOUtil;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import picard.cmdline.CommandLineProgramTest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class CollectSequencingArtifactMetricsTest extends CommandLineProgramTest {
private static final File TEST_DIR = new File("testdata/picard/analysis/artifacts/CollectSequencingArtifactMetrics");
private static final File REFERENCE = new File(TEST_DIR, "test.fasta");
private static final File TEST_SAM = new File(TEST_DIR, "test.sam");
private static final File DB_SNP = new File(TEST_DIR, "test.dbsnp.vcf");
private static final File INTERVALS = new File(TEST_DIR, "test.interval_list");
private static final File TEST_CASES = new File(TEST_DIR, "ExpectedMetricsOutput");
private File globalTempOutputDir;
@Override
public String getCommandLineProgramName() {
return CollectSequencingArtifactMetrics.class.getSimpleName();
}
@BeforeTest
public void setUp() throws IOException {
globalTempOutputDir = IOUtil.createTempDir("artifactMetrics.", ".tmp");
}
@AfterTest
public void tearDown() throws IOException {
IOUtil.deleteDirectoryTree(globalTempOutputDir);
}
/**
* Run the CLP using standard arguments and maybe some additional ones, then compare to the expected results.
*
* @param testCase name of test case (should match one of the file sets in {@code TEST_CASES}
* @param extraArgs extra arguments of the form {@code "KEY1=VALUE1", "KEY2=VALUE2"}, etc. These can override standard args.
* @return the base path of the output metrics
*/
private void runAnalysis(final String testCase, final String ... extraArgs) throws IOException {
final File actual = new File(globalTempOutputDir, testCase);
final File expected = new File(TEST_CASES, testCase);
final Map<String, String> args = new HashMap<String, String>();
args.put("INPUT", TEST_SAM.getAbsolutePath());
args.put("OUTPUT", actual.getAbsolutePath());
args.put("REFERENCE_SEQUENCE", REFERENCE.getAbsolutePath());
args.put("MINIMUM_INSERT_SIZE", "30"); // test data has this insert size
args.put("MAXIMUM_INSERT_SIZE", "30"); // test data has this insert size
args.put("CONTEXT_SIZE", "0"); // ignore context by default, to cut down on file size
for (final String extraArg : extraArgs) {
final String[] kv = extraArg.split("=");
args.put(kv[0], kv[1]);
}
runPicardCommandLine(args);
assertAllFilesEqual(expected, actual);
}
private void assertAllFilesEqual(final File expectedBase, final File actualBase) {
Assert.assertTrue(areMetricsEqual(expectedBase, actualBase, SequencingArtifactMetrics.PRE_ADAPTER_SUMMARY_EXT),"Pre-Adapter summary files differ.");
Assert.assertTrue(areMetricsEqual(expectedBase, actualBase, SequencingArtifactMetrics.PRE_ADAPTER_DETAILS_EXT),"Pre-Adapter details files differ.");
Assert.assertTrue(areMetricsEqual(expectedBase, actualBase, SequencingArtifactMetrics.BAIT_BIAS_SUMMARY_EXT), "Bait-Bias summary files differ.");
Assert.assertTrue(areMetricsEqual(expectedBase, actualBase, SequencingArtifactMetrics.BAIT_BIAS_DETAILS_EXT), "Bait-bias details files differ.");
Assert.assertTrue(areMetricsEqual(expectedBase, actualBase, SequencingArtifactMetrics.ERROR_SUMMARY_EXT), "Error-summary files differ.");
}
private boolean areMetricsEqual(final File expectedBase, final File actualBase, final String extension) {
return MetricsFile.areMetricsEqual(new File(expectedBase + extension), new File(actualBase + extension));
}
@Test
public void testContext() throws IOException {
runAnalysis("with_context", "CONTEXT_SIZE=1");
}
@Test
public void testDbSnp() throws IOException {
runAnalysis("with_dbsnp", "DB_SNP=" + DB_SNP);
}
@Test
public void testIntervalList() throws IOException {
runAnalysis("with_intervals", "INTERVALS=" + INTERVALS);
}
@Test
public void testNoBqCutoff() throws IOException {
runAnalysis("no_bq_cutoff", "MINIMUM_QUALITY_SCORE=0");
}
@Test
public void testNoMqCutoff() throws IOException {
runAnalysis("no_mq_cutoff", "MINIMUM_MAPPING_QUALITY=0");
}
@Test
public void testUnmappedMate() throws IOException {
runAnalysis("unmapped_mate", "MINIMUM_INSERT_SIZE=0", "MAXIMUM_INSERT_SIZE=0");
}
}