public double GetGenotypeLogLikelihood(Balleles gtObservedCounts, PhasedGenotype gtModelCount)
        {
            double minLogLikelihood     = Math.Log(1.0 / Double.MaxValue);
            double currentLogLikelihood = 0;

            foreach (var gtCount in gtObservedCounts.GetTruncatedAlleleCounts())
            {
                int    rowId               = Math.Min(gtCount.Item1, _maxCoverage - 1);
                int    colId               = Math.Min(gtCount.Item2, _maxCoverage - 1);
                int    numHapsNonZero      = (gtModelCount.CopyNumberA > 0 ? 1 : 0) + (gtModelCount.CopyNumberB > 0 ? 1 : 0);
                double likelihoodThisLocus = 0;
                // the observations can arise from a het locus, if both copy numbers are positive
                if (numHapsNonZero == 2)
                {
                    // Given a variant locus with two haplotypes, we have a roughly 2/3 chance of it being het.
                    // Alleles have 50:50 chance of being 'A' or 'B'.
                    // We ignore error terms, as they should have a negligible impact here.
                    likelihoodThisLocus += 1.0 / 3.0 *
                                           (
                        _alleleDistribution[gtModelCount.CopyNumberA][gtModelCount.CopyNumberB].Item1[rowId] *
                        _alleleDistribution[gtModelCount.CopyNumberA][gtModelCount.CopyNumberB].Item2[colId]
                        +
                        _alleleDistribution[gtModelCount.CopyNumberA][gtModelCount.CopyNumberB].Item1[colId] *
                        _alleleDistribution[gtModelCount.CopyNumberA][gtModelCount.CopyNumberB].Item2[rowId]
                                           );
                }
                // they can also arise from a hom locus in various ways
                if (numHapsNonZero > 0)
                {
                    // these should be constants to avoid calling Log over and over.
                    double logErrorProb   = Math.Log(0.01);
                    double logNoErrorProb = Math.Log(.99);
                    // If both haplotypes have non-zero depth and the locus is non-ref, a locus has a prior prob of 1/3 of being hom,
                    // assuming a well-mixed population.  We could adjust for observed het:hom, but we do not at this time.
                    // Of course, if only one haplotype has non-zero depth, it must be hom.
                    double priorFactorHom = numHapsNonZero == 2 ? 0.5 * (1.0 / 3.0) : 1.0;
                    // limit ttlReads to maxTotalDepth as that is all we have _readDepth probabilities for
                    int totalReads = Math.Min(rowId + colId, _maxAlleleCounts);
                    int totalCN    = gtModelCount.CopyNumberA + gtModelCount.CopyNumberB;
                    // Split the likelihood into two parts:
                    // First, the probability of getting the observed total number of reads, given the total copy number
                    double probTotalReadDepth = _totalAlleleCountsDistribution[totalCN][totalReads];
                    // Second, the probability of the observed per-allele read counts assuming one of the alleles is an error.
                    // The calculation here is simply binomial, in log space
                    double logProbCountAErrors = LogCombinations(rowId, colId) + rowId * logErrorProb + colId * logNoErrorProb;
                    double logProbCountBErrors = LogCombinations(rowId, colId) + colId * logErrorProb + rowId * logNoErrorProb;

                    likelihoodThisLocus += priorFactorHom * probTotalReadDepth * (
                        Math.Exp(logProbCountAErrors) + Math.Exp(logProbCountBErrors));
                }
                else
                {
                    // uses alleleStateZeroCorrector to enable non-zero likelihoods
                    int totalReads = Math.Min(rowId + colId, _maxAlleleCounts);
                    likelihoodThisLocus = _totalAlleleCountsDistribution[0][totalReads];
                }

                likelihoodThisLocus   = Math.Max(minLogLikelihood, likelihoodThisLocus);
                currentLogLikelihood += Math.Log(likelihoodThisLocus);
            }
            return(currentLogLikelihood);
        }