// decide whether we are currently processing SNPs, indels, neither, or both
  private List<GenotypeLikelihoodsCalculationModel.Model> getGLModelsToUse(
      final RefMetaDataTracker tracker,
      final ReferenceContext refContext,
      final AlignmentContext rawContext) {

    final List<GenotypeLikelihoodsCalculationModel.Model> models =
        new ArrayList<GenotypeLikelihoodsCalculationModel.Model>(2);
    String modelPrefix = "";
    if (UAC.GLmodel.name().toUpperCase().contains("BOTH"))
      modelPrefix = UAC.GLmodel.name().toUpperCase().replaceAll("BOTH", "");

    if (!UAC.GLmodel.name().contains(GPSTRING)
        && UAC.samplePloidy != VariantContextUtils.DEFAULT_PLOIDY)
      modelPrefix = GPSTRING + modelPrefix;

    // if we're genotyping given alleles and we have a requested SNP at this position, do SNP
    if (UAC.GenotypingMode
        == GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES) {
      final VariantContext vcInput =
          getVCFromAllelesRod(
              tracker, refContext, rawContext.getLocation(), false, logger, UAC.alleles);
      if (vcInput == null) return models;

      if (vcInput.isSNP()) {
        // ignore SNPs if the user chose INDEL mode only
        if (UAC.GLmodel.name().toUpperCase().contains("BOTH")
            || UAC.GLmodel.name().toUpperCase().contains("SNP"))
          models.add(GenotypeLikelihoodsCalculationModel.Model.valueOf(modelPrefix + "SNP"));
      } else if (vcInput.isIndel() || vcInput.isMixed()) {
        // ignore INDELs if the user chose SNP mode only
        if (UAC.GLmodel.name().toUpperCase().contains("BOTH")
            || UAC.GLmodel.name().toUpperCase().contains("INDEL"))
          models.add(GenotypeLikelihoodsCalculationModel.Model.valueOf(modelPrefix + "INDEL"));
      }
      // No support for other types yet
    } else {
      if (UAC.GLmodel.name().toUpperCase().contains("BOTH")) {
        models.add(GenotypeLikelihoodsCalculationModel.Model.valueOf(modelPrefix + "SNP"));
        models.add(GenotypeLikelihoodsCalculationModel.Model.valueOf(modelPrefix + "INDEL"));
      } else {
        models.add(
            GenotypeLikelihoodsCalculationModel.Model.valueOf(
                modelPrefix + UAC.GLmodel.name().toUpperCase()));
      }
    }

    return models;
  }
  // private method called by both UnifiedGenotyper and UGCalcLikelihoods entry points into the
  // engine
  private VariantContext calculateLikelihoods(
      final RefMetaDataTracker tracker,
      final ReferenceContext refContext,
      final Map<String, AlignmentContext> stratifiedContexts,
      final AlignmentContextUtils.ReadOrientation type,
      final List<Allele> alternateAllelesToUse,
      final boolean useBAQedPileup,
      final GenotypeLikelihoodsCalculationModel.Model model,
      final Map<String, org.broadinstitute.sting.utils.genotyper.PerReadAlleleLikelihoodMap>
          perReadAlleleLikelihoodMap) {

    // initialize the data for this thread if that hasn't been done yet
    if (glcm.get() == null) {
      glcm.set(getGenotypeLikelihoodsCalculationObject(logger, UAC));
    }

    return glcm.get()
        .get(model.name().toUpperCase())
        .getLikelihoods(
            tracker,
            refContext,
            stratifiedContexts,
            type,
            alternateAllelesToUse,
            useBAQedPileup && BAQEnabledOnCMDLine,
            genomeLocParser,
            perReadAlleleLikelihoodMap);
  }
  private Map<String, AlignmentContext> getFilteredAndStratifiedContexts(
      UnifiedArgumentCollection UAC,
      ReferenceContext refContext,
      AlignmentContext rawContext,
      final GenotypeLikelihoodsCalculationModel.Model model) {

    if (!BaseUtils.isRegularBase(refContext.getBase())) return null;

    Map<String, AlignmentContext> stratifiedContexts = null;

    if (model.name().contains("INDEL")) {

      final ReadBackedPileup pileup =
          rawContext.getBasePileup().getMappingFilteredPileup(UAC.MIN_BASE_QUALTY_SCORE);
      // don't call when there is no coverage
      if (pileup.getNumberOfElements() == 0 && UAC.OutputMode != OUTPUT_MODE.EMIT_ALL_SITES)
        return null;

      // stratify the AlignmentContext and cut by sample
      stratifiedContexts = AlignmentContextUtils.splitContextBySampleName(pileup);

    } else if (model.name().contains("SNP")) {

      // stratify the AlignmentContext and cut by sample
      stratifiedContexts =
          AlignmentContextUtils.splitContextBySampleName(rawContext.getBasePileup());

      if (!(UAC.OutputMode == OUTPUT_MODE.EMIT_ALL_SITES
          && UAC.GenotypingMode
              != GenotypeLikelihoodsCalculationModel.GENOTYPING_MODE.GENOTYPE_GIVEN_ALLELES)) {
        int numDeletions = 0;
        for (final PileupElement p : rawContext.getBasePileup()) {
          if (p.isDeletion()) numDeletions++;
        }
        if (((double) numDeletions) / ((double) rawContext.getBasePileup().getNumberOfElements())
            > UAC.MAX_DELETION_FRACTION) {
          return null;
        }
      }
    }

    return stratifiedContexts;
  }
 protected double getTheta(final GenotypeLikelihoodsCalculationModel.Model model) {
   if (model.name().contains("SNP")) return HUMAN_SNP_HETEROZYGOSITY;
   if (model.name().contains("INDEL")) return HUMAN_INDEL_HETEROZYGOSITY;
   else throw new IllegalArgumentException("Unexpected GenotypeCalculationModel " + model);
 }
 protected double[] getAlleleFrequencyPriors(
     final GenotypeLikelihoodsCalculationModel.Model model) {
   if (model.name().toUpperCase().contains("SNP")) return log10AlleleFrequencyPriorsSNPs;
   else if (model.name().toUpperCase().contains("INDEL")) return log10AlleleFrequencyPriorsIndels;
   else throw new IllegalArgumentException("Unexpected GenotypeCalculationModel " + model);
 }
 /**
  * Compute genotypes at a given locus.
  *
  * @param vc the GL-annotated variant context
  * @return the VariantCallContext object
  */
 public VariantCallContext calculateGenotypes(VariantContext vc) {
   return calculateGenotypes(
       null, null, null, null, vc, GenotypeLikelihoodsCalculationModel.Model.valueOf("SNP"), null);
 }