05316c62e54dfd3cac589a1ae6001e84c357959b angie Mon Apr 23 08:24:28 2012 -0700 Feature #6152 (Variant Annotation Tool): enhancement to filter logic:filters can be for inclusion or exclusion when the condition is met, based on the new filter->isExclude. When a filter is set to rightJoin and it is for inclusion, annoGratorIntegrate propagates rightJoin failure if no rows overlap since the condition for inclusion has not been met. diff --git src/lib/annoGrator.c src/lib/annoGrator.c index 7a43c74..7a103b9 100644 --- src/lib/annoGrator.c +++ src/lib/annoGrator.c @@ -101,45 +101,52 @@ } } struct annoRow *annoGratorIntegrate(struct annoGrator *self, struct annoRow *primaryRow, boolean *retRJFilterFailed) /* Given a single row from the primary source, get all overlapping rows from internal * source, and produce joined output rows. If retRJFilterFailed is non-NULL and any * overlapping row has a rightJoin filter failure (see annoFilter.h), * set retRJFilterFailed and stop. */ { struct annoRow *rowList = NULL; agCheckPrimarySorting(self, primaryRow); agTrimToStart(self, primaryRow->chrom, primaryRow->start); agFetchToEnd(self, primaryRow->chrom, primaryRow->end); boolean rjFailHard = (retRJFilterFailed != NULL); +if (rjFailHard) + *retRJFilterFailed = FALSE; struct annoRow *qRow; for (qRow = self->qHead; qRow != NULL; qRow = qRow->next) { if (qRow->start < primaryRow->end && qRow->end > primaryRow->start && sameString(qRow->chrom, primaryRow->chrom)) { slAddHead(&rowList, annoRowClone(qRow, self->mySource)); if (rjFailHard && qRow->rightJoinFail) { *retRJFilterFailed = TRUE; break; } } } slReverse(&rowList); +// If no rows overlapped primary, and there is a right-join, !isExclude (i.e. isInclude) filter, +// then we need to set retRJFilterFailed because the condition was not met to include +// the primary item. +if (rowList == NULL && rjFailHard && self->haveRJIncludeFilter) + *retRJFilterFailed = TRUE; return rowList; } void annoGratorClose(struct annoStreamer **pSelf) /* Free self (including mySource). */ { if (pSelf == NULL) return; struct annoGrator *self = *(struct annoGrator **)pSelf; annoRowFreeList(&(self->qHead), self->mySource); self->mySource->close(&(self->mySource)); freeMem(self->prevPChrom); freez(pSelf); } @@ -148,48 +155,68 @@ { errAbort("nextRow() called on annoGrator object, but integrate() should be called instead"); return NULL; } static void agReset(struct annoGrator *self) /* Reset all position associated with state */ { freez(&self->prevPChrom); self->prevPStart = 0; self->eof = FALSE; annoRowFreeList(&(self->qHead), (struct annoStreamer *)self); self->qTail = NULL; } +static boolean filtersHaveRJInclude(struct annoFilter *filters) +/* Return TRUE if filters have at least one active filter with !isExclude && rightJoin. */ +{ +struct annoFilter *filter; +for (filter = filters; filter != NULL; filter = filter->next) + if (filter->op != afNoFilter && !filter->isExclude && filter->rightJoin) + return TRUE; +return FALSE; +} + +static void agSetFilters(struct annoStreamer *vSelf, struct annoFilter *newFilters) +/* Update filters and re-evaluate self->haveRJIncludeFilter */ +{ +annoStreamerSetFilters(vSelf, newFilters); +struct annoGrator *self = (struct annoGrator *)vSelf; +self->haveRJIncludeFilter = filtersHaveRJInclude(vSelf->filters); +} + void annoGratorSetRegion(struct annoStreamer *vSelf, char *chrom, uint rStart, uint rEnd) /* Set genomic region for query, and reset internal state. */ { struct annoGrator *self = (struct annoGrator *)vSelf; self->mySource->setRegion((struct annoStreamer *)(self->mySource), chrom, rStart, rEnd); agReset(self); } void annoGratorSetQuery(struct annoStreamer *vSelf, struct annoGratorQuery *query) /* Set query (to be called only by annoGratorQuery which is created after streamers). */ { struct annoGrator *self = (struct annoGrator *)vSelf; self->streamer.query = query; self->mySource->setQuery((struct annoStreamer *)(self->mySource), query); } struct annoGrator *annoGratorNew(struct annoStreamer *mySource) /* Make a new integrator of columns from mySource with (positions of) rows passed to integrate(). * mySource becomes property of the new annoGrator. */ { struct annoGrator *self; AllocVar(self); struct annoStreamer *streamer = &(self->streamer); annoStreamerInit(streamer, mySource->getAutoSqlObject(mySource)); streamer->rowType = mySource->rowType; +streamer->setFilters = agSetFilters; streamer->setRegion = annoGratorSetRegion; streamer->setQuery = annoGratorSetQuery; streamer->nextRow = noNextRow; streamer->close = annoGratorClose; self->integrate = annoGratorIntegrate; self->mySource = mySource; +self->haveRJIncludeFilter = filtersHaveRJInclude(streamer->filters); return self; }