e62655df7abb8c2ab44f5b11798f6f6c731afded angie Wed Oct 5 15:42:05 2011 -0700 Feature #3710 (vcfTabix UI options): added optional filter on min QUAL score. diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c index 8617c79..14ab5c6 100644 --- src/hg/hgTracks/vcfTrack.c +++ src/hg/hgTracks/vcfTrack.c @@ -6,68 +6,99 @@ #include "errCatch.h" #include "hacTree.h" #include "hdb.h" #include "hgTracks.h" #include "pgSnp.h" #include "trashDir.h" #include "vcf.h" #include "vcfUi.h" #if (defined USE_TABIX && defined KNETFILE_HOOKS) #include "knetUdc.h" #include "udc.h" #endif//def USE_TABIX && KNETFILE_HOOKS #ifdef USE_TABIX -static boolean getFilterValues(struct trackDb *tdb, struct slName **retValues) +static boolean getMinQual(struct trackDb *tdb, double *retMinQual, boolean compositeLevel) +/* Return TRUE and set retMinQual id cart contains minimum QUAL filter */ +{ +char cartVar[512]; +safef(cartVar, sizeof(cartVar), "%s."VCF_APPLY_MIN_QUAL_VAR, tdb->track); +if (cartUsualBooleanClosestToHome(cart, tdb, compositeLevel, + VCF_APPLY_MIN_QUAL_VAR, VCF_DEFAULT_APPLY_MIN_QUAL)) + { + if (retMinQual != NULL) + *retMinQual = cartUsualDoubleClosestToHome(cart, tdb, compositeLevel, VCF_MIN_QUAL_VAR, + VCF_DEFAULT_MIN_QUAL); + return TRUE; + } +return FALSE; +} + +static boolean minQualFail(struct vcfRecord *record, double minQual) +/* Return TRUE if record's QUAL column value is non-numeric or is less than minQual. */ +{ +if (isEmpty(record->qual) || + (record->qual[0] != '-' && !isdigit(record->qual[0])) || + atof(record->qual) < minQual) + return TRUE; +return FALSE; +} + +static boolean getFilterValues(struct trackDb *tdb, struct slName **retValues, + boolean compositeLevel) /* Return TRUE and set retValues if cart contains FILTER column values to exclude */ { char cartVar[512]; -safef(cartVar, sizeof(cartVar), "%s.exclude_filterColumn", tdb->track); +safef(cartVar, sizeof(cartVar), "%s."VCF_EXCLUDE_FILTER_VAR, tdb->track); if (cartListVarExists(cart, cartVar)) { struct slName *selectedValues = cartOptionalSlNameList(cart, cartVar); if (retValues != NULL) *retValues = selectedValues; return TRUE; } return FALSE; } -static boolean excludeRecord(struct vcfRecord *record, struct slName *filterValues) +static boolean filterColumnFail(struct vcfRecord *record, struct slName *filterValues) /* Return TRUE if record's FILTER column value(s) matches one of filterValues (from cart). */ { int i; for (i = 0; i < record->filterCount; i++) if (slNameInList(filterValues, record->filters[i])) return TRUE; return FALSE; } static void filterRecords(struct vcfFile *vcff, struct trackDb *tdb) /* If a filter is specified in the cart, remove any records that don't pass filter. */ { +boolean compositeLevel = isNameAtCompositeLevel(tdb, tdb->track); +double minQual = 0; struct slName *filterValues = NULL; -boolean gotFilter = getFilterValues(tdb, &filterValues); -if (!gotFilter) +boolean gotQualFilter = getMinQual(tdb, &minQual, compositeLevel); +boolean gotFilterFilter = getFilterValues(tdb, &filterValues, compositeLevel); +if (! (gotQualFilter || gotFilterFilter) ) return; struct vcfRecord *rec, *nextRec, *newList = NULL; for (rec = vcff->records; rec != NULL; rec = nextRec) { nextRec = rec->next; - if (!excludeRecord(rec, filterValues)) + if (! ((gotQualFilter && minQualFail(rec, minQual)) || + (gotFilterFilter && filterColumnFail(rec, filterValues))) ) slAddHead(&newList, rec); } slReverse(&newList); vcff->records = newList; } static struct pgSnp *vcfFileToPgSnp(struct vcfFile *vcff, struct trackDb *tdb) /* Convert vcff's records to pgSnp; don't free vcff until you're done with pgSnp * because it contains pointers into vcff's records' chrom. */ { struct pgSnp *pgsList = NULL; struct vcfRecord *rec; int maxLen = 33; for (rec = vcff->records; rec != NULL; rec = rec->next) {