/** * Finalize, if appropriate, all derived data in recalibrationTables. * * <p>Called once after all calls to updateDataForRead have been issued. * * <p>Assumes that all of the principal tables (by quality score) have been completely updated, * and walks over this data to create summary data tables like by read group table. */ public void finalizeData() { if (finalized) throw new IllegalStateException("FinalizeData() has already been called"); // merge all of the thread-local tables finalRecalibrationTables = mergeThreadLocalRecalibrationTables(); final NestedIntegerArray<RecalDatum> byReadGroupTable = finalRecalibrationTables.getReadGroupTable(); final NestedIntegerArray<RecalDatum> byQualTable = finalRecalibrationTables.getQualityScoreTable(); // iterate over all values in the qual table for (final NestedIntegerArray.Leaf<RecalDatum> leaf : byQualTable.getAllLeaves()) { final int rgKey = leaf.keys[0]; final int eventIndex = leaf.keys[2]; final RecalDatum rgDatum = byReadGroupTable.get(rgKey, eventIndex); final RecalDatum qualDatum = leaf.value; if (rgDatum == null) { // create a copy of qualDatum, and initialize byReadGroup table with it byReadGroupTable.put(new RecalDatum(qualDatum), rgKey, eventIndex); } else { // combine the qual datum with the existing datum in the byReadGroup table rgDatum.combine(qualDatum); } } finalized = true; }
/** * Update the recalibration statistics using the information in recalInfo * * @param recalInfo data structure holding information about the recalibration values for a single * read */ @Requires("recalInfo != null") public void updateDataForRead(final ReadRecalibrationInfo recalInfo) { final GATKSAMRecord read = recalInfo.getRead(); final ReadCovariates readCovariates = recalInfo.getCovariatesValues(); final RecalibrationTables tables = getUpdatableRecalibrationTables(); final NestedIntegerArray<RecalDatum> qualityScoreTable = tables.getQualityScoreTable(); for (int offset = 0; offset < read.getReadBases().length; offset++) { if (!recalInfo.skip(offset)) { for (final EventType eventType : EventType.values()) { final int[] keys = readCovariates.getKeySet(offset, eventType); final int eventIndex = eventType.ordinal(); final byte qual = recalInfo.getQual(eventType, offset); final double isError = recalInfo.getErrorFraction(eventType, offset); RecalUtils.incrementDatumOrPutIfNecessary( qualityScoreTable, qual, isError, keys[0], keys[1], eventIndex); for (int i = 2; i < covariates.length; i++) { if (keys[i] < 0) continue; RecalUtils.incrementDatumOrPutIfNecessary( tables.getTable(i), qual, isError, keys[0], keys[1], keys[i], eventIndex); } } } } }
/** * Merge all of the thread local recalibration tables into a single one. * * <p>Reuses one of the recalibration tables to hold the merged table, so this function can only * be called once in the engine. * * @return the merged recalibration table */ @Requires("! finalized") private RecalibrationTables mergeThreadLocalRecalibrationTables() { if (recalibrationTablesList.isEmpty()) { recalibrationTablesList.add( new RecalibrationTables(covariates, numReadGroups, maybeLogStream)); } RecalibrationTables merged = null; for (final RecalibrationTables table : recalibrationTablesList) { if (merged == null) // fast path -- if there's only only one table, so just make it the merged one merged = table; else { merged.combine(table); } } return merged; }