/**
   * 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);
          }
        }
      }
    }
  }