diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java index 0cd1882df..2acff956c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/GenotypeConcordance.java @@ -75,22 +75,43 @@ public class GenotypeConcordance extends RodWalker genotypeFilterExpressionsEval = new ArrayList(); + + @Argument(shortName="gfc", fullName="genotypeFilterExpressionComp", doc="One or more criteria to use to set COMP genotypes to no-call. "+ + "These genotype-level filters are only applied to the COMP rod.", required=false) + public ArrayList genotypeFilterExpressionsComp = new ArrayList(); + + @Argument(shortName="moltenize",fullName="moltenize",doc="Molten rather than tabular output") + public boolean moltenize = false; + @Output PrintStream out; - List evalSamples; - List compSamples; + private List evalSamples; + private List compSamples; + private List evalJexls = null; + private List compJexls = null; - // todo -- deal with occurrences like: - // Eval: 20 4000 A C - // Eval: 20 4000 A AC - // Comp: 20 4000 A C - // currently this results in a warning and skipping - // todo -- extend to multiple eval, multiple comp // todo -- table with "proportion of overlapping sites" (not just eval/comp margins) - // todo -- genotype-level filtering + // todo -- moltenize + public void initialize() { + evalJexls = initializeJexl(genotypeFilterExpressionsEval); + compJexls = initializeJexl(genotypeFilterExpressionsComp); + } + + private List initializeJexl(ArrayList genotypeFilterExpressions) { + ArrayList dummyNames = new ArrayList(genotypeFilterExpressions.size()); + int expCount = 1; + for ( String exp : genotypeFilterExpressions ) { + dummyNames.add(String.format("gfe%d",expCount++)); + } + return VariantContextUtils.initializeMatchExps(dummyNames, genotypeFilterExpressions); + } + public ConcordanceMetrics reduceInit() { Map headerMap = GATKVCFUtils.getVCFHeadersFromRods(getToolkit(), Arrays.asList(evalBinding,compBinding)); VCFHeader evalHeader = headerMap.get(evalBinding.getName()); @@ -110,15 +131,19 @@ public class GenotypeConcordance extends RodWalker eval = tracker.getValues(evalBinding,ref.getLocus()); List comp = tracker.getValues(compBinding,ref.getLocus()); if ( eval.size() > 1 || comp.size() > 1 ) { - logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving."); - evalCompPair = resolveMultipleRecords(eval,comp); + if ( noDuplicateTypes(eval) && noDuplicateTypes(comp) ) { + logger.info("Eval or Comp Rod at position " + ref.getLocus().toString() + " has multiple records. Resolving."); + evalCompPair = resolveMultipleRecords(eval,comp); + } else { + logger.warn("Eval or Comp Rod at position "+ref.getLocus().toString()+" has multiple records of the same type. This locus will be skipped."); + } } else { // if a rod is missing, explicitly create a variant context with 'missing' genotypes. Slow, but correct. // note that if there is no eval rod there must be a comp rod, and also the reverse VariantContext evalContext = eval.size() == 1 ? eval.get(0) : createEmptyContext(comp.get(0),evalSamples); VariantContext compContext = comp.size() == 1 ? comp.get(0) : createEmptyContext(eval.get(0),compSamples); - evalContext = filterGenotypes(evalContext,ignoreFilters); - compContext = filterGenotypes(compContext,ignoreFilters); + evalContext = filterGenotypes(evalContext,ignoreFilters,evalJexls); + compContext = filterGenotypes(compContext,ignoreFilters,compJexls); evalCompPair.add(new Pair(evalContext,compContext)); } } @@ -126,9 +151,21 @@ public class GenotypeConcordance extends RodWalker vcList) { + HashSet types = new HashSet(vcList.size()); + for ( VariantContext vc : vcList ) { + VariantContext.Type type = vc.getType(); + if ( types.contains(type) ) + return false; + types.add(type); + } + + return true; + } + /** - * The point of this method is to match up pairs of evals and comps by their alternate alleles. Basically multiple records could - * exist for a site such as: + * The point of this method is to match up pairs of evals and comps by their type (or alternate alleles for mixed). + * Basically multiple records could exist for a site such as: * Eval: 20 4000 A C * Eval: 20 4000 A AC * Comp: 20 4000 A C @@ -146,14 +183,19 @@ public class GenotypeConcordance extends RodWalker> resolvedPairs = new ArrayList>(evalList.size()+compList.size()); // oversized but w/e List pairedEval = new ArrayList(evalList.size()); for ( VariantContext eval : evalList ) { - Set evalAlts = new HashSet(eval.getAlternateAlleles()); + VariantContext.Type evalType = eval.getType(); + Set evalAlleles = new HashSet(eval.getAlternateAlleles()); VariantContext pairedComp = null; for ( VariantContext comp : compList ) { - for ( Allele compAlt : comp.getAlternateAlleles() ) { - if ( evalAlts.contains(compAlt) ) { - // matching alt allele, pair these records - pairedComp = comp; - break; + if ( evalType.equals(comp.getType()) ) { + pairedComp = comp; + break; + } else if ( eval.isMixed() || comp.isMixed() ) { + for ( Allele compAllele : comp.getAlternateAlleles() ) { + if ( evalAlleles.contains(compAllele) ) { + pairedComp = comp; + break; + } } } } @@ -197,83 +239,202 @@ public class GenotypeConcordance extends RodWalker entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { - ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); - concordanceEvalProportions.set(entry.getKey(),"Sample",entry.getKey()); - concordanceCompProportions.set(entry.getKey(),"Sample",entry.getKey()); - concordanceCounts.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCompProportions.addColumn("Eval_Genotype","%s"); + concordanceCounts.addColumn("Eval_Genotype","%s"); + concordanceEvalProportions.addColumn("Eval_Genotype","%s"); + concordanceSummary.addColumn("Non-Reference_Discrepancy","%.3f"); + + concordanceCompProportions.addColumn("Comp_Genotype","%s"); + concordanceCounts.addColumn("Comp_Genotype","%s"); + concordanceEvalProportions.addColumn("Comp_Genotype","%s"); + concordanceSummary.addColumn("Non-Reference_Sensitivity","%.3f"); + + concordanceCompProportions.addColumn("Proportion","%.3f"); + concordanceCounts.addColumn("Count","%d"); + concordanceEvalProportions.addColumn("Proportion","%.3f"); + + for ( Map.Entry entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { + ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String rowKey = String.format("%s_%s_%s",entry.getKey(),evalType.toString(),compType.toString()); + concordanceCounts.set(rowKey,"Sample",entry.getKey()); + concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCounts.set(rowKey,"Comp_Genotype",evalType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(rowKey,"Count",count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) { + concordanceEvalProportions.set(rowKey,"Sample",entry.getKey()); + concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + } + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) { + concordanceCompProportions.set(rowKey,"Sample",entry.getKey()); + concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + } + String mismatchKey = String.format("%s_%s",entry.getKey(),"Mismatching"); + concordanceCounts.set(mismatchKey,"Sample",entry.getKey()); + concordanceCounts.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCounts.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Sample",entry.getKey()); + concordanceEvalProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(mismatchKey,"Sample",entry.getKey()); + concordanceCompProportions.set(mismatchKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(mismatchKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(mismatchKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(mismatchKey,"Count",table.getnMismatchingAlt()); + } + + String sampleKey = "ALL"; + ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String rowKey = String.format("%s_%s_%s",sampleKey,evalType.toString(),compType.toString()); + concordanceCounts.set(rowKey,"Sample",sampleKey); + concordanceCounts.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCounts.set(rowKey,"Comp_Genotype",evalType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(rowKey,"Count",count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) { + concordanceEvalProportions.set(rowKey,"Sample",sampleKey); + concordanceEvalProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceEvalProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + } + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) { + concordanceCompProportions.set(rowKey,"Sample",sampleKey); + concordanceCompProportions.set(rowKey,"Eval_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Comp_Genotype",evalType.toString()); + concordanceCompProportions.set(rowKey,"Proportion",repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + } + String rowKey = String.format("%s_%s",sampleKey,"Mismatching"); + concordanceCounts.set(rowKey,"Sample",sampleKey); + concordanceCounts.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCounts.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Sample",sampleKey); + concordanceEvalProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(rowKey,"Sample",sampleKey); + concordanceCompProportions.set(rowKey,"Eval_Genotype","Mismatching_Alleles"); + concordanceCompProportions.set(rowKey,"Comp_Genotype","Mismatching_Alleles"); + concordanceEvalProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(rowKey,"Proportion", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(rowKey,"Count",table.getnMismatchingAlt()); + + for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { + concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); + concordanceSummary.set(nrsEntry.getKey(),"Non-Reference_Sensitivity",nrsEntry.getValue()); + } + for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { + concordanceSummary.set(nrdEntry.getKey(),"Non-Reference_Discrepancy",nrdEntry.getValue()); + } + concordanceSummary.set("ALL_NRS_NRD","Sample","ALL"); + concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Sensitivity",metrics.getOverallNRS()); + concordanceSummary.set("ALL_NRS_NRD","Non-Reference_Discrepancy",metrics.getOverallNRD()); + + + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.addColumn(type.toString(),"%d"); + } + + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + } + + } else { + concordanceCompProportions.addColumn("Sample","%s"); + concordanceCounts.addColumn("Sample","%s"); + concordanceEvalProportions.addColumn("Sample","%s"); + concordanceSummary.addColumn("Sample","%s"); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String colKey = String.format("%s_%s", evalType.toString(), compType.toString()); + concordanceCounts.addColumn(colKey,"%d"); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) + concordanceEvalProportions.addColumn(colKey,"%.3f"); + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) + concordanceCompProportions.addColumn(colKey,"%.3f"); + } + } + concordanceEvalProportions.addColumn("Mismatching_Alleles","%.3f"); + concordanceCompProportions.addColumn("Mismatching_Alleles","%.3f"); + concordanceCounts.addColumn("Mismatching_Alleles","%d"); + concordanceSummary.addColumn("Non-Reference Sensitivity","%.3f"); + concordanceSummary.addColumn("Non-Reference Discrepancy","%.3f"); + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.addColumn(type.toString(),"%d"); + } + + for ( Map.Entry entry : metrics.getPerSampleGenotypeConcordance().entrySet() ) { + ConcordanceMetrics.GenotypeConcordanceTable table = entry.getValue(); + concordanceEvalProportions.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCompProportions.set(entry.getKey(),"Sample",entry.getKey()); + concordanceCounts.set(entry.getKey(),"Sample",entry.getKey()); + for ( GenotypeType evalType : GenotypeType.values() ) { + for ( GenotypeType compType : GenotypeType.values() ) { + String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); + int count = table.get(evalType, compType); + concordanceCounts.set(entry.getKey(),colKey,count); + if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) + concordanceEvalProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) + concordanceCompProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + } + } + concordanceEvalProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(entry.getKey(),"Mismatching_Alleles",table.getnMismatchingAlt()); + } + + String rowKey = "ALL"; + concordanceCompProportions.set(rowKey,"Sample",rowKey); + concordanceEvalProportions.set(rowKey,"Sample",rowKey); + concordanceCounts.set(rowKey,"Sample",rowKey); + ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); for ( GenotypeType evalType : GenotypeType.values() ) { for ( GenotypeType compType : GenotypeType.values() ) { String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); - int count = table.get(evalType, compType); - concordanceCounts.set(entry.getKey(),colKey,count); + int count = table.get(evalType,compType); + concordanceCounts.set(rowKey,colKey,count); if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) - concordanceEvalProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); + concordanceEvalProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) - concordanceCompProportions.set(entry.getKey(),colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + concordanceCompProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); } } - concordanceEvalProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); - concordanceCompProportions.set(entry.getKey(),"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); - concordanceCounts.set(entry.getKey(),"Mismatching_Alleles",table.getnMismatchingAlt()); - } + concordanceEvalProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); + concordanceCompProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); + concordanceCounts.set(rowKey,"Mismatching_Alleles",table.getnMismatchingAlt()); - String rowKey = "ALL"; - concordanceCompProportions.set(rowKey,"Sample",rowKey); - concordanceEvalProportions.set(rowKey,"Sample",rowKey); - concordanceCounts.set(rowKey,"Sample",rowKey); - ConcordanceMetrics.GenotypeConcordanceTable table = metrics.getOverallGenotypeConcordance(); - for ( GenotypeType evalType : GenotypeType.values() ) { - for ( GenotypeType compType : GenotypeType.values() ) { - String colKey = String.format("%s_%s",evalType.toString(),compType.toString()); - int count = table.get(evalType,compType); - concordanceCounts.set(rowKey,colKey,count); - if ( evalType == GenotypeType.HET || evalType == GenotypeType.HOM_REF || evalType == GenotypeType.HOM_VAR) - concordanceEvalProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnEvalGenotypes(evalType))); - if ( compType == GenotypeType.HET || compType == GenotypeType.HOM_VAR || compType == GenotypeType.HOM_REF ) - concordanceCompProportions.set(rowKey,colKey,repairNaN(( (double) count)/table.getnCompGenotypes(compType))); + for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { + concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); + concordanceSummary.set(nrsEntry.getKey(),"Non-Reference Sensitivity",nrsEntry.getValue()); } - } - concordanceEvalProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledEvalGenotypes())); - concordanceCompProportions.set(rowKey,"Mismatching_Alleles", repairNaN(( (double) table.getnMismatchingAlt() )/table.getnCalledCompGenotypes())); - concordanceCounts.set(rowKey,"Mismatching_Alleles",table.getnMismatchingAlt()); + for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { + concordanceSummary.set(nrdEntry.getKey(),"Non-Reference Discrepancy",nrdEntry.getValue()); + } + concordanceSummary.set("ALL","Sample","ALL"); + concordanceSummary.set("ALL","Non-Reference Sensitivity",metrics.getOverallNRS()); + concordanceSummary.set("ALL","Non-Reference Discrepancy",metrics.getOverallNRD()); - for ( Map.Entry nrsEntry : metrics.getPerSampleNRS().entrySet() ) { - concordanceSummary.set(nrsEntry.getKey(),"Sample",nrsEntry.getKey()); - concordanceSummary.set(nrsEntry.getKey(),"Non-Reference Sensitivity",nrsEntry.getValue()); - } - for ( Map.Entry nrdEntry : metrics.getPerSampleNRD().entrySet() ) { - concordanceSummary.set(nrdEntry.getKey(),"Non-Reference Discrepancy",nrdEntry.getValue()); - } - concordanceSummary.set("ALL","Sample","ALL"); - concordanceSummary.set("ALL","Non-Reference Sensitivity",metrics.getOverallNRS()); - concordanceSummary.set("ALL","Non-Reference Discrepancy",metrics.getOverallNRD()); - - for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { - siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + for (ConcordanceMetrics.SiteConcordanceType type : ConcordanceMetrics.SiteConcordanceType.values() ) { + siteConcordance.set("Comparison",type.toString(),metrics.getOverallSiteConcordance().get(type)); + } } report.addTable(concordanceCompProportions); @@ -298,13 +459,32 @@ public class GenotypeConcordance extends RodWalker exps) { // placeholder method for genotype-level filtering. However if the site itself is filtered, // and such filters are not ignored, the genotype-level data should be altered to reflect this + if ( ! context.isFiltered() || ignoreSiteFilter ) { - // todo -- add genotype-level jexl filtering here - return context; + List filteredGenotypes = new ArrayList(context.getNSamples()); + for ( Genotype g : context.getGenotypes() ) { + Map matchMap = VariantContextUtils.match(context, g, exps); + boolean filtered = false; + for ( Boolean b : matchMap.values() ) { + if ( b ) { + filtered = true; + break; + } + } + if ( filtered ) { + filteredGenotypes.add(GenotypeBuilder.create(g.getSampleName(),Arrays.asList(Allele.NO_CALL,Allele.NO_CALL),g.getExtendedAttributes())); + } else { + filteredGenotypes.add(g); + } + } + VariantContextBuilder builder = new VariantContextBuilder(context); + builder.genotypes(filteredGenotypes); + return builder.make(); } + VariantContextBuilder builder = new VariantContextBuilder(); builder.alleles(Arrays.asList(context.getReference())); builder.loc(context.getChr(),context.getStart(),context.getEnd());