---
# System prepended metadata

title: GATK-GVCF
tags: [survey]

---

###### tags: `survey`
{%hackmd Eg_dogKwTYGxkdzZ3O5Gkg %}
# GATK-GVCF

## Flow
```mermaid
flowchart
  subgraph referenceModelForNoVariation
    direction TB
    S1(finalizeRegion)-->S2(filterNonPassingReads)
    S2-->S3(calculateRefConfidence)
  end

A1 --"not active"--> referenceModelForNoVariation
A1(("region")) --"active"--> A2(trim haplotypes/reads)
A2 --> A3(left flank)
A2 --> A5(right flank)
A3 --> referenceModelForNoVariation
A5 --> referenceModelForNoVariation
A2 --> A4(trimmed region)
A4 --> S3
```

## calculateRefConfidence
```mermaid
flowchart
  subgraph makeReferenceConfidenceVariantContext
    direction TB
    S1(calcGenotypeLikelihoodsOfRefVsAny)-->S2(add some tags: AD, DP...)
    S2-->S3(doIndelRefConfCalc)
  end
A1((For each pos)) -->A2(pileup base and BQ)
A2 --"overlappingSite"-->A3("use PL from modified read-allele likelihood(*)")
A2 --"!overlappingSite"-->makeReferenceConfidenceVariantContext
```


### finalizeRegion
- trim reads base on setting (soft, hard, BQ thresholds...)
- modify pairs overlapping BQ 

### filterNonPassingReads
- filtering following reads
    - unclip read too short (<10)
    - has mate but mate not in same contig
    - RG setting

### calcGenotypeLikelihoodsOfRefVsAny
![](https://i.imgur.com/zYcxpb6.png)

### doIndelRefConfCalc
- choose PL be the one in { PL from calcGenotypeLikelihoodsOfRefVsAny, PL_indel} with the smaller GQ.
- PL_indel can be computed base on N = #{reads that have no plausible indels based on alignment at pileup}
- For convenience, PL_indel = [0,3N,45N]
- [N, informative reads](#Informative-reads)
![](https://i.imgur.com/r34YkUG.png)
![](https://i.imgur.com/SSnDmCG.png)
![](https://i.imgur.com/1WHe3Lx.png)
![](https://i.imgur.com/erTYvJ2.png)
20221131_cohort.pptx


### PL from modified read-allele likelihood
- base on original read-allele likelihood
- add <NON_REF> allele and it's likelihood
- the value of NON_REF would be $$\text{median(likelihoods < best allele likelihood)}$$
![](https://i.imgur.com/y9vuTpF.png)

### Informative reads
```java
private static boolean readHasNoPlausibleIdealsOfSize(final GATKRead read,
                                                      final int readStart,
                                                      final byte[] refBases,
                                                      final int refStart,
                                                      final int maxIndelSize,
                                                      final boolean useCachedResults) {
    BitSet cachedResult = (BitSet) read.getTransientAttribute(INDEL_INFORMATIVE_BASES_CACHE_ATTRIBUTE_NAME);
    // 計算過的會放到 tag IDL 裡面暫存
    if (cachedResult == null || !useCachedResults) {
        Utils.validate(readStart >= 0, "readStart must >= 0");
        Utils.validate(refStart >= 0, "refStart must >= 0");
        BitSet informativeBases = new BitSet(read.getLength());

        if ( !(read.getLength() - readStart < maxIndelSize) && !(refBases.length - refStart < maxIndelSize) ) {
            // readStart後長度 >= maxIndelSize 且 refStart後長度 >= maxIndelSize

            final int secondaryReadBreakPosition = read.getLength() - maxIndelSize;
            // 倒數 maxIndelSize 個 base
            
            final Pair<byte[], byte[]> readBasesAndBaseQualities = AlignmentUtils.getBasesAndBaseQualitiesAlignedOneToOne(read);
            // calls getBasesNoCopy if CIGAR is all match
            // get base & BQ
            // for the delection part, fill "-" into base, and fill "0" into BQ
            // for the softclip & insertion part, copy base & BQ in reads
            // 
            // For example (deletion):
            // read          AAAA   AAA       4444   444
            // ref           AAAAAAAAAA       
            // =>            AAAA---AAA       4444000444
            // 
            // For example (insertion):
            // read          AAAAAAAAAA       4444444444
            // ref           AAAA   AAA
            // =>            AAAAAAAAAA       4444444444

            final byte[] readBases = readBasesAndBaseQualities.getLeft();
            final byte[] readQualities = readBasesAndBaseQualities.getRight();

            if (readBases.length - readStart > maxIndelSize) {
            // read.len() != readBases.len() when there is a deletion

                final int lastReadBaseToMarkAsIndelRelevant;
                final boolean referenceWasShorter;
                if (readBases.length < refBases.length - refStart + readStart + 1) {
                    lastReadBaseToMarkAsIndelRelevant = readBases.length - maxIndelSize;
                    referenceWasShorter = false;
                } else {
                    lastReadBaseToMarkAsIndelRelevant = refBases.length - refStart + readStart - maxIndelSize + 1;
                    referenceWasShorter = true;
                }
                // 檢查 ref.len - refstart 長還是 readBase - readStart 長
//              // 看要 先算多少個base

                final int[] baselineMisMatchSums = calculateBaselineMMQualities(readBases, readQualities, readStart, refBases, refStart);
                // for each base, accumulate all BQ of mismatch bases after(contains) this base
                // for example
                // AAAAAAAAAAA    BQ: 91999399959
                // ATAAATAAATA
                // =>                 88777755550
                
                for (int indelSize = 1; indelSize <= maxIndelSize; indelSize++) {
                    // Computing mismatches corresponding to a deletion
                    traverseEndOfReadForIndelMismatches(informativeBases,
                            readStart,
                            readBases,
                            readQualities,
                            lastReadBaseToMarkAsIndelRelevant,
                            secondaryReadBreakPosition,
                            refStart,
                            refBases,
                            baselineMisMatchSums,
                            indelSize,
                            false);

                    // Computing mismatches corresponding to an insertion
                    traverseEndOfReadForIndelMismatches(informativeBases,
                            readStart,
                            readBases,
                            readQualities,
                            lastReadBaseToMarkAsIndelRelevant,
                            secondaryReadBreakPosition,
                            refStart,
                            refBases,
                            baselineMisMatchSums,
                            indelSize,
                            true);
                }

                if ( lastReadBaseToMarkAsIndelRelevant <= secondaryReadBreakPosition) {
                    informativeBases.flip(0, lastReadBaseToMarkAsIndelRelevant);
                    // 對錯互換

                    if (referenceWasShorter) {
                        informativeBases.set(lastReadBaseToMarkAsIndelRelevant - 1, false);
                    }
                } else {
                    informativeBases.flip(0, secondaryReadBreakPosition + 1);
                }

            }
        }
        cachedResult = informativeBases;
        read.setTransientAttribute(INDEL_INFORMATIVE_BASES_CACHE_ATTRIBUTE_NAME, informativeBases);
    }
    return cachedResult.get(readStart);
}
private static void traverseEndOfReadForIndelMismatches(final BitSet informativeBases, final int readStart, final byte[] readBases, 
                                                        final byte[] readQuals, final int lastReadBaseToMarkAsIndelRelevant, 
                                                        final int secondaryReadBreakPosition, final int refStart, final byte[] refBases, 
                                                        final int[] baselineMMSums, final int indelSize, final boolean insertion) {
    final int globalMismatchCostForReadAlignedToReference = baselineMMSums[0];
    // accumulate BQ > 此值就 break
    int baseQualitySum = 0;

    final int insertionLength = !insertion ? 0 : indelSize;
    final int deletionLength = insertion ? 0 : indelSize;

    final int numberOfBasesToDirectlyCompare = Math.min(readBases.length - readStart - insertionLength,
            refBases.length - refStart - deletionLength);

    for (int readOffset = numberOfBasesToDirectlyCompare + insertionLength - 1,
         refOffset = numberOfBasesToDirectlyCompare + deletionLength - 1;
         readOffset >= 0 && refOffset >= 0;
         readOffset--, refOffset--) {
        // 從尾巴開始向前

        final byte readBase = readBases[readStart + readOffset];
        final byte refBase = refBases[refStart + refOffset];
        if (isMismatchAndNotAnAlignmentGap(readBase, refBase)) {
            // If mismatch
            baseQualitySum += readQuals[readStart + readOffset];
            // accumulate BQ
            if (baseQualitySum > globalMismatchCostForReadAlignedToReference) {
                // 如果累積的超過最大值, 代表往前的 base 不會 support indel
                break;
            }
        }
        int siteOfRealComparisonPoint = Math.min(readOffset, refOffset);

        if (readBases[readStart + siteOfRealComparisonPoint] != AlignmentUtils.GAP_CHARACTER &&
            // if read[pos] != "-" (本來的 deletion 捕的值)
                readStart + siteOfRealComparisonPoint < lastReadBaseToMarkAsIndelRelevant &&
                readStart + siteOfRealComparisonPoint <= secondaryReadBreakPosition &&
                baselineMMSums[siteOfRealComparisonPoint] >= baseQualitySum) {
            // 如果baseline 的 accumulate BQ >= BQ, 則設定此點是 un-informative
            informativeBases.set(readStart + siteOfRealComparisonPoint, true);
            // 他這最後會 filp 一次, 所以錯就是對, 對就是錯
        }
    }
}
```