f08f66f3653ea11d306641ad089ad7dc085b8ba1 tdreszer Tue Nov 23 14:02:10 2010 -0800 Added format type drop down to advanced search tab. Whitelist is in code and all code is wrapped with ifdefs when feature becomes more of a hassle than it is worth at this time. diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c index a50001b..7448d2b 100644 --- src/hg/hgTracks/searchTracks.c +++ src/hg/hgTracks/searchTracks.c @@ -16,30 +16,31 @@ #include "jksql.h" #include "hdb.h" #include "mdb.h" #include "trix.h" #include "jsHelper.h" #include "imageV2.h" #define ANYLABEL "Any" #define TRACK_SEARCH_FORM "trackSearch" #define SEARCH_RESULTS_FORM "searchResults" #define METADATA_NAME_PREFIX "hgt_mdbVar" #define METADATA_VALUE_PREFIX "hgt_mdbVal" #define TRACK_SEARCH_CURRENT_TAB "tsCurTab" #define TRACK_SEARCH_SIMPLE "tsSimple" #define TRACK_SEARCH_ON_NAME "tsName" +#define TRACK_SEARCH_ON_TYPE "tsType" #define TRACK_SEARCH_ON_GROUP "tsGroup" #define TRACK_SEARCH_ON_DESCR "tsDescr" #define TRACK_SEARCH_SORT "tsSort" static int gCmpGroup(const void *va, const void *vb) /* Compare groups based on label. */ { const struct group *a = *((struct group **)va); const struct group *b = *((struct group **)vb); return strcmp(a->label, b->label); } // Would like to do a radio button choice ofsorts enum sortBy { @@ -157,30 +158,108 @@ labels[ix] = cloneString(ANYLABEL); values[ix] = cloneString(ANYLABEL); struct slPair *pair = NULL; while((pair = slPopHead(&pairs)) != NULL) { ix++; labels[ix] = pair->name; values[ix] = pair->val; freeMem(pair); } *pLabels = labels; *pTerms = values; return count; } +#ifdef TRACK_SEARCH_ON_TYPE +static int getFormatTypes(char ***pLabels, char ***pTypes) +{ +char *crudeTypes[] = { + ANYLABEL, + //"altGraphX", + "bam", + "psl", + "chain", + "netAlign", + "maf", + "bed", + "bigBed", + "ctgPos", + "expRatio", + "genePred", + "broadPeak", + "narrowPeak", + "rmsk", + "bedGraph", + "bigWig", + "wig", + "wigMaf", +}; +// Non-standard: +// type altGraphX +// type axt +// type bed5FloatScore +// type bed5FloatScoreWithFdr +// type chromGraph +// type clonePos +// type coloredExon +// type encodeFiveC +// type factorSource +// type ld2 +// type logo +// type maf +// type sample +// type wigMafProt 0.0 1.0 + +char *nicerTypes[] = { + ANYLABEL, + //"altGraphX", + "Alignment binary (bam) - binary SAM", + "Alignment Blast (psl) - Blast output", + "Alignment Chains (chain) - Pairwise alignment", + "Alignment Nets (netAlign) - Net alignments", + "Alignments (maf) - multiple alignment format", + "bed - browser extensible data", + "bigBed - self index, often remote bed format", + "ctgPos - Contigs", + "expRatio - Expression ratios", + "Genes (genePred) - Gene prediction and annotation", + "Peaks Broad (broadPeak) - ENCODE large region peak format", + "Peaks Narrow (narrowPeak) - ENCODE small region peak format", + "Repeats (rmsk) - Repeat masking", + "Signal (bedGraph) - graphically represented bed data", + "Signal (bigWig) - self index, often remote wiggle format", + "Signal (wig) - wiggle format" + "Signal (wigMaf) - multiple alignment wiggle", +}; +#endif///def TRACK_SEARCH_ON_TYPE + +int ix = 0, count = sizeof(crudeTypes)/sizeof(char *); +char **labels; +char **values; +AllocArray(labels, count); +AllocArray(values, count); +for(ix=0;ix<count;ix++) + { + labels[ix] = cloneString(nicerTypes[ix]); + values[ix] = cloneString(crudeTypes[ix]); + } +*pLabels = labels; +*pTypes = values; +return count; +} + static int metaDbVars(struct sqlConnection *conn, char *** metaVars, char *** metaLabels) // Search the assemblies metaDb table; If name == NULL, we search every metadata field. { char query[256]; struct slPair *oneTerm,*whiteList = mdbCvWhiteList(TRUE,FALSE); int count =0, whiteCount = slCount(whiteList); char **retVar = needMem(sizeof(char *) * whiteCount); char **retLab = needMem(sizeof(char *) * whiteCount); for(oneTerm=whiteList;oneTerm!=NULL;oneTerm=oneTerm->next) { safef(query, sizeof(query), "select count(*) from metaDb where var = '%s'",oneTerm->name); if(sqlQuickNum(conn,query) > 0) { retVar[count] = oneTerm->name; @@ -358,38 +437,38 @@ { struct slRef *tracks = NULL; struct trixSearchResult *tsList; for(tsList = trixSearch(trix, descWordCount, descWords, TRUE); tsList != NULL; tsList = tsList->next) { struct track *track = (struct track *) hashFindVal(trackHash, tsList->itemId); if (track != NULL) // It is expected that this is NULL (e.g. when the trix references trackDb tracks which have no tables) { refAdd(&tracks, track); } } return tracks; } -static struct slRef *advancedSearchForTracks(struct sqlConnection *conn,struct group *groupList, char **descWords,int descWordCount, char *nameSearch, char *descSearch, char *groupSearch, +static struct slRef *advancedSearchForTracks(struct sqlConnection *conn,struct group *groupList, char **descWords,int descWordCount, char *nameSearch, char *typeSearch, char *descSearch, char *groupSearch, int numMetadataNonEmpty,int numMetadataSelects,char **mdbVar,char **mdbVal) // Performs the advanced search and returns the found tracks. { int tracksFound = 0; struct slRef *tracks = NULL; - if(!isEmpty(nameSearch) || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty) + if(!isEmpty(nameSearch) || typeSearch != NULL || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty) { // First do the metaDb searches, which can be done quickly for all tracks with db queries. struct hash *matchingTracks = newHash(0); struct slName *el, *metaTracks = NULL; int i; for(i = 0; i < numMetadataSelects; i++) { if(!isEmpty(mdbVal[i])) { #ifdef CV_SEARCH_SUPPORTS_FREETEXT enum mdbCvSearchable searchBy = mdbCvSearchMethod(mdbVar[i]); struct slName *tmp = NULL; // If select is by free text then like if (searchBy == cvsSearchByMultiSelect) @@ -444,61 +523,80 @@ } for (el = metaTracks; el != NULL; el = el->next) hashAddInt(matchingTracks, el->name, 1); struct group *group; for (group = groupList; group != NULL; group = group->next) { if(groupSearch == NULL || sameString(group->name, groupSearch)) { if (group->trackList != NULL) { struct trackRef *tr; for (tr = group->trackList; tr != NULL; tr = tr->next) { struct track *track = tr->track; + #ifdef TRACK_SEARCH_ON_TYPE + char *trackType = cloneFirstWord(track->tdb->type); + #endif///def TRACK_SEARCH_ON_TYPE if((isEmpty(nameSearch) || isNameMatch(track, nameSearch, "contains")) && + #ifdef TRACK_SEARCH_ON_TYPE + (isEmpty(typeSearch) || (sameWord(typeSearch, trackType) && !tdbIsComposite(track->tdb))) && + //(isEmpty(typeSearch) || sameWord(typeSearch, trackType)) && + #endif///def TRACK_SEARCH_ON_TYPE (isEmpty(descSearch) || isDescriptionMatch(track, descWords, descWordCount)) && (!numMetadataNonEmpty || hashLookup(matchingTracks, track->track) != NULL)) { if (track != NULL) { tracksFound++; refAdd(&tracks, track); } else warn("found group track is NULL."); } + #ifdef TRACK_SEARCH_ON_TYPE + freeMem(trackType); + #endif///def TRACK_SEARCH_ON_TYPE if (track->subtracks != NULL) { struct track *subTrack; for (subTrack = track->subtracks; subTrack != NULL; subTrack = subTrack->next) { + #ifdef TRACK_SEARCH_ON_TYPE + trackType = cloneFirstWord(subTrack->tdb->type); + #endif///def TRACK_SEARCH_ON_TYPE if((isEmpty(nameSearch) || isNameMatch(subTrack, nameSearch, "contains")) && + #ifdef TRACK_SEARCH_ON_TYPE + (isEmpty(typeSearch) || sameWord(typeSearch, trackType)) && + #endif///def TRACK_SEARCH_ON_TYPE (isEmpty(descSearch) || isDescriptionMatch(subTrack, descWords, descWordCount)) && (!numMetadataNonEmpty || hashLookup(matchingTracks, subTrack->track) != NULL)) { // XXXX to parent hash. - use tdb->parent instead. //hashAdd(parents, subTrack->track, track); if (track != NULL) { tracksFound++; refAdd(&tracks, subTrack); } else warn("found subtrack is NULL."); } + #ifdef TRACK_SEARCH_ON_TYPE + freeMem(trackType); + #endif///def TRACK_SEARCH_ON_TYPE } } } } } } } return tracks; } #define MAX_FOUND_TRACKS 100 static void findTracksPageLinks(int tracksFound, int startFrom) { if (tracksFound <= MAX_FOUND_TRACKS) @@ -738,56 +836,62 @@ void doSearchTracks(struct group *groupList) { if (!advancedJavascriptFeaturesEnabled(cart)) { warn("Requires advanced javascript features."); return; } struct group *group; char *groups[128]; char *labels[128]; int numGroups = 1; groups[0] = ANYLABEL; labels[0] = ANYLABEL; char *currentTab = cartUsualString(cart, TRACK_SEARCH_CURRENT_TAB, "simpleTab"); char *nameSearch = cartOptionalString(cart, TRACK_SEARCH_ON_NAME); +#ifdef TRACK_SEARCH_ON_TYPE +char *typeSearch = cartOptionalString(cart, TRACK_SEARCH_ON_TYPE); +#endif///def TRACK_SEARCH_ON_TYPE char *descSearch; char *groupSearch = cartOptionalString(cart, TRACK_SEARCH_ON_GROUP); boolean doSearch = sameString(cartOptionalString(cart, TRACK_SEARCH), "Search") || cartUsualInt(cart, TRACK_SEARCH_PAGER, -1) >= 0; struct sqlConnection *conn = hAllocConn(database); boolean metaDbExists = sqlTableExists(conn, "metaDb"); int numMetadataSelects, tracksFound = 0; int numMetadataNonEmpty = 0; char **mdbVar = NULL; char **mdbVal = NULL; #ifdef ONE_FUNC struct hash *parents = newHash(4); #endif///def ONE_FUNC boolean simpleSearch; struct trix *trix; char trixFile[HDB_MAX_PATH_STRING]; char **descWords = NULL; int descWordCount = 0; boolean searchTermsExist = FALSE; int cols; char buf[512]; if(sameString(currentTab, "simpleTab")) { descSearch = cartOptionalString(cart, TRACK_SEARCH_SIMPLE); simpleSearch = TRUE; freez(&nameSearch); +#ifdef TRACK_SEARCH_ON_TYPE + freez(&typeSearch); +#endif///def TRACK_SEARCH_ON_TYPE freez(&groupSearch); } else { descSearch = cartOptionalString(cart, TRACK_SEARCH_ON_DESCR); simpleSearch = FALSE; } if(descSearch) stripChar(descSearch, '"'); trackList = getTrackList(&groupList, -2); // global makeGlobalTrackHash(trackList); // NOTE: This is necessary when container cfg by '*' results in vis changes // This will handle composite/view override when subtrack specific vis exists, AND superTrack reshaping. @@ -867,78 +971,99 @@ hPrintf("<input type='text' name='%s' id='descSearch' value='%s' class='submitOnEnter' onkeyup='findTracksSearchButtonsEnable(true);' style='max-width:536px; width:536px; font-size:.9em;'>", TRACK_SEARCH_ON_DESCR, descSearch == NULL ? "" : descSearch); hPrintf("</td></tr>\n"); if (!simpleSearch && descSearch) searchTermsExist = TRUE; hPrintf("<tr><td colspan=2></td><td align='right'>and </td>\n"); hPrintf("<td><b style='max-width:100px;'>Group:</b></td>"); hPrintf("<td align='right'>is</td>\n"); hPrintf("<td colspan='%d'>", cols - 4); cgiMakeDropListFull(TRACK_SEARCH_ON_GROUP, labels, groups, numGroups, groupSearch, "class='groupSearch' style='min-width:40%; font-size:.9em;'"); hPrintf("</td></tr>\n"); if (!simpleSearch && groupSearch) searchTermsExist = TRUE; +#ifdef TRACK_SEARCH_ON_TYPE +// Track Type is (drop down) +hPrintf("<tr><td colspan=2></td><td align='right'>and </td>\n"); +hPrintf("<td nowrap><b style='max-width:100px;'>Data Format:</b></td>"); +hPrintf("<td align='right'>is</td>\n"); +hPrintf("<td colspan='%d'>", cols - 4); +char **formatTypes = NULL; +char **formatLabels = NULL; +int formatCount = getFormatTypes(&formatLabels, &formatTypes); +cgiMakeDropListFull(TRACK_SEARCH_ON_TYPE, formatLabels, formatTypes, formatCount, typeSearch, "class='typeSearch' style='min-width:40%; font-size:.9em;'"); +hPrintf("</td></tr>\n"); +if (!simpleSearch && typeSearch) + searchTermsExist = TRUE; +#endif///def TRACK_SEARCH_ON_TYPE + // Metadata selects require careful accounting if(metaDbExists) numMetadataSelects = printMdbSelects(conn, cart, simpleSearch, &mdbVar, &mdbVal, &numMetadataNonEmpty, cols); else numMetadataSelects = 0; hPrintf("</table>\n"); hPrintf("<input type='submit' name='%s' id='searchSubmit' value='search' style='font-size:.8em;'>\n", TRACK_SEARCH); hPrintf("<input type='button' name='clear' value='clear' class='clear' style='font-size:.8em;' onclick='findTracksClear();'>\n"); hPrintf("<input type='submit' name='submit' value='cancel' class='cancel' style='font-size:.8em;'>\n"); //hPrintf("<a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a>\n"); hPrintf("</div>\n</div>\n"); hPrintf("</form>\n"); hPrintf("</div>"); // Restricts to max-width:1000px; if(descSearch != NULL && !strlen(descSearch)) descSearch = NULL; if(groupSearch != NULL && sameString(groupSearch, ANYLABEL)) groupSearch = NULL; +if(typeSearch != NULL && sameString(typeSearch, ANYLABEL)) + typeSearch = NULL; if(!isEmpty(descSearch)) { char *tmp = cloneString(descSearch); char *val = nextWord(&tmp); struct slName *el, *descList = NULL; int i; while (val != NULL) { slNameAddTail(&descList, val); descWordCount++; val = nextWord(&tmp); } descWords = needMem(sizeof(char *) * descWordCount); for(i = 0, el = descList; el != NULL; i++, el = el->next) descWords[i] = strLower(el->name); } if (doSearch && simpleSearch && descWordCount <= 0) doSearch = FALSE; if(doSearch) { // Now search struct slRef *tracks = NULL; if(simpleSearch) tracks = simpleSearchForTracksstruct(trix,descWords,descWordCount); else - tracks = advancedSearchForTracks(conn,groupList,descWords,descWordCount,nameSearch,descSearch,groupSearch,numMetadataNonEmpty,numMetadataSelects,mdbVar,mdbVal); +#ifdef TRACK_SEARCH_ON_TYPE + tracks = advancedSearchForTracks(conn,groupList,descWords,descWordCount,nameSearch,typeSearch,descSearch,groupSearch,numMetadataNonEmpty,numMetadataSelects,mdbVar,mdbVal); +#else///ifndef TRACK_SEARCH_ON_TYPE + tracks = advancedSearchForTracks(conn,groupList,descWords,descWordCount,nameSearch,NULL,descSearch,groupSearch,numMetadataNonEmpty,numMetadataSelects,mdbVar,mdbVal); +#endif///ndef TRACK_SEARCH_ON_TYPE // Sort and Print results enum sortBy sortBy = cartUsualInt(cart,TRACK_SEARCH_SORT,sbRelevance); tracksFound = slCount(tracks); if(tracksFound > 1) findTracksSort(&tracks,simpleSearch,sortBy); displayFoundTracks(cart,tracks,tracksFound,sortBy); } hFreeConn(&conn); webNewSection("About Track Search"); if(metaDbExists) hPrintf("<p>Search for terms in track names, descriptions, groups, and ENCODE " "metadata. If multiple terms are entered, only tracks with all terms "