1 package org.broadinstitute.hellbender.tools.dragstr; 2 3 import org.broadinstitute.hellbender.engine.GATKPath; 4 import org.broadinstitute.hellbender.utils.Utils; 5 import org.broadinstitute.hellbender.utils.dragstr.DragstrParamUtils; 6 import org.broadinstitute.hellbender.utils.dragstr.DragstrParams; 7 import org.broadinstitute.hellbender.utils.tsv.DataLine; 8 import org.broadinstitute.hellbender.utils.tsv.TableReader; 9 import org.testng.Assert; 10 import org.testng.annotations.Test; 11 12 import java.io.File; 13 import java.io.IOException; 14 import java.nio.file.Path; 15 16 /** 17 * Tests the {@link DragstrParametersEstimator} code. 18 */ 19 public class DragstrParametersEstimatorTest { 20 21 private static final Path DRAGEN_USED_CASES = new File("src/test/resources/large/org/broadinstitute/hellbender/tools/dragstr/dragen-param-estimator-input.tab.gz").toPath(); 22 private static final Path DRAGEN_ESPECTED_RESULT = new File("src/test/resources/large/org/broadinstitute/hellbender/tools/dragstr/dragen-param-estimator-expected-output.txt").toPath(); 23 private static final DragstrHyperParameters HYPER_PARAMETERS = new DragstrHyperParameters(); 24 25 @Test testMatchWithDragenValues()26 public void testMatchWithDragenValues() { 27 final StratifiedDragstrLocusCases cases = composeInputCases(); 28 final DragstrParametersEstimator subject = new DragstrParametersEstimator(HYPER_PARAMETERS); 29 final DragstrParams actual = Utils.runInParallel(0, () -> subject.estimate(cases)); 30 final DragstrParams expected = DragstrParamUtils.parse(new GATKPath(DRAGEN_ESPECTED_RESULT.toString())); 31 Assert.assertEquals(actual.maximumPeriod(), expected.maximumPeriod()); 32 Assert.assertEquals(actual.maximumRepeats(), expected.maximumRepeats()); 33 for (int i = 1; i <= actual.maximumPeriod(); i++) { 34 for (int j = 1; j <= actual.maximumRepeats(); j++) { 35 Assert.assertEquals(roundOf(actual.gop(i,j)), roundOf(expected.gop(i,j))); 36 Assert.assertEquals(roundOf(actual.gcp(i,j)), roundOf(expected.gcp(i,j))); 37 Assert.assertEquals(roundOf(actual.api(i,j)), roundOf(expected.api(i,j))); 38 } 39 } 40 } 41 roundOf(final double dbl)42 private double roundOf(final double dbl) { 43 return Math.round(100 * dbl) / 100.0; 44 } 45 composeInputCases()46 private StratifiedDragstrLocusCases composeInputCases() { 47 try (final DRAGENEstimationDataReader reader = new DRAGENEstimationDataReader(DRAGEN_USED_CASES)) { 48 return reader.stream() 49 .map(DRAGENEstimationDataRecord::toCase) 50 .reduce(StratifiedDragstrLocusCases.make(HYPER_PARAMETERS.maxPeriod, HYPER_PARAMETERS.maxRepeatLength), 51 (accu, caze) -> { accu.add(caze); return accu; }, 52 StratifiedDragstrLocusCases::merge); 53 } catch (final IOException ex) { 54 Assert.fail("can't read input data test file: " + DRAGEN_USED_CASES, ex); 55 throw new RuntimeException("this should not be reached"); 56 } 57 } 58 59 static class DRAGENEstimationDataReader extends TableReader<DRAGENEstimationDataRecord> { DRAGENEstimationDataReader(final Path path)60 DRAGENEstimationDataReader(final Path path) throws IOException { 61 super(path); 62 } 63 64 @Override createRecord(DataLine dataLine)65 protected DRAGENEstimationDataRecord createRecord(DataLine dataLine) { 66 return new DRAGENEstimationDataRecord( 67 dataLine.getInt(), // 0 68 dataLine.getLong(), // 1 69 dataLine.getInt(), // 2 70 dataLine.getInt(), // 3 71 dataLine.seek(6).getInt(), // 6 because we skip operiod (4) and orepeat (5) columns. 72 dataLine.getInt()); // 7 73 } 74 } 75 76 static class DRAGENEstimationDataRecord { 77 private final int chrIdx; 78 private final long pos; 79 private final int period; 80 private final int repeats; 81 private final int n; 82 private final int k; 83 DRAGENEstimationDataRecord(int chrIdx, long pos, int period, int repeats, int n, int k)84 private DRAGENEstimationDataRecord(int chrIdx, long pos, int period, int repeats, int n, int k) { 85 this.chrIdx = chrIdx; 86 this.pos = pos; 87 this.period = period; 88 this.repeats = repeats; 89 this.n = n; 90 this.k = k; 91 } 92 toCase()93 private DragstrLocusCase toCase() { 94 // 0 mask is irrelevant as these don't affect the test. 95 final DragstrLocus locus = DragstrLocus.make(chrIdx, pos, (byte) period, (short) (period * repeats), 0); 96 // 60,0 minMQ,nSup are not relevant as these do not affect the test. 97 return DragstrLocusCase.create(locus, n, k, 60, 0); 98 } 99 } 100 } 101