b8aea5bf5b28fc6430dac4b3b301253188e52310 max Fri Jun 20 06:42:00 2025 -0700 added help note after intersect button, refs #34110 diff --git src/hg/hgTables/mainPage.c src/hg/hgTables/mainPage.c index 7fdfc02a4dd..4ff8f7ba276 100644 --- src/hg/hgTables/mainPage.c +++ src/hg/hgTables/mainPage.c @@ -1,1225 +1,1227 @@ /* mainPage - stuff to put up the first table browser page. */ /* Copyright (C) 2014 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "htmshell.h" #include "cheapcgi.h" #include "cart.h" #include "cartTrackDb.h" #include "textOut.h" #include "jksql.h" #include "hdb.h" #include "web.h" #include "jsHelper.h" #include "hui.h" #include "hgColors.h" #include "trackDb.h" #include "grp.h" #include "hgTables.h" #include "joiner.h" #include "trackDb.h" #include "hubConnect.h" #include "trackHub.h" #include "hgConfig.h" static struct dyString *onChangeStart() /* Start up a javascript onChange command */ { struct dyString *dy = jsOnChangeStart(); jsDropDownCarryOver(dy, hgtaTrack); jsDropDownCarryOver(dy, hgtaGroup); jsTrackedVarCarryOver(dy, hgtaRegionType, "regionType"); jsTextCarryOver(dy, hgtaRange); jsDropDownCarryOver(dy, hgtaOutputType); jsTextCarryOver(dy, hgtaOutFileName); return dy; } static char *onChangeClade() /* Return javascript executed when they change clade. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, hgtaTable); dyStringAppend(dy, " document.hiddenForm.org.value=0;"); dyStringAppend(dy, " document.hiddenForm.db.value=0;"); dyStringAppend(dy, " document.hiddenForm.position.value='';"); return jsOnChangeEnd(&dy); } static char *onChangeOrg() /* Return javascript executed when they change organism. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, "org"); jsDropDownCarryOver(dy, hgtaTable); dyStringAppend(dy, " document.hiddenForm.db.value=0;"); dyStringAppend(dy, " document.hiddenForm.position.value='';"); return jsOnChangeEnd(&dy); } static char *onChangeDb() /* Return javascript executed when they change database. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, "db"); jsDropDownCarryOver(dy, hgtaTable); dyStringAppend(dy, " document.hiddenForm.position.value='';"); return jsOnChangeEnd(&dy); } static char *onChangeGroupOrTrack() /* Return javascript executed when they change group. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, "db"); jsDropDownCarryOver(dy, "org"); dyStringPrintf(dy, " document.hiddenForm.%s.value=0;", hgtaTable); return jsOnChangeEnd(&dy); } static char *onChangeTable() /* Return javascript executed when they change group. */ { struct dyString *dy = onChangeStart(); jsDropDownCarryOver(dy, "clade"); jsDropDownCarryOver(dy, "db"); jsDropDownCarryOver(dy, "org"); jsDropDownCarryOver(dy, hgtaTable); return jsOnChangeEnd(&dy); } void makeRegionButtonExtraHtml(char *val, char *selVal, char *extraHtml) /* Make region radio button including a little Javascript to save selection state * and optional extra html attributes. */ { jsMakeTrackingRadioButtonExtraHtml(hgtaRegionType, "regionType", val, selVal, extraHtml); } void makeRegionButton(char *val, char *selVal) /* Make region radio button including a little Javascript * to save selection state. */ { makeRegionButtonExtraHtml(val, selVal, NULL); } struct grp *showGroupField(char *groupVar, char *event, char *groupScript, struct sqlConnection *conn, boolean allTablesOk) /* Show group control. Returns selected group. */ { struct grp *group, *groupList = fullGroupList; struct grp *selGroup = findSelectedGroup(groupList, groupVar); hPrintf("Group:\n"); hPrintf("\n"); return selGroup; } static void addIfExists(struct hash *hash, struct slName **pList, char *name) /* Add name to tail of list if it exists in hash. */ { if (hashLookup(hash, name)) slNameAddTail(pList, name); } struct slName *getDbListForGenome() /* Get list of selectable databases. */ { struct hash *hash = sqlHashOfDatabases(); struct slName *dbList = NULL; addIfExists(hash, &dbList, database); addIfExists(hash, &dbList, "uniProt"); addIfExists(hash, &dbList, "proteome"); addIfExists(hash, &dbList, "go"); addIfExists(hash, &dbList, "hgFixed"); addIfExists(hash, &dbList, "visiGene"); addIfExists(hash, &dbList, "ultra"); return dbList; } char *findSelDb() /* Find user selected database (as opposed to genome database). */ { struct slName *dbList = getDbListForGenome(); char *selDb = cartUsualString(cart, hgtaTrack, NULL); if (!slNameInList(dbList, selDb)) selDb = cloneString(dbList->name); slFreeList(&dbList); return selDb; } struct trackDb *showTrackField(struct grp *selGroup, char *trackVar, char *event, char *trackScript, boolean disableNoGenome) /* Show track control. Returns selected track. */ { struct trackDb *track, *selTrack = NULL; if (trackScript == NULL) trackScript = ""; if (sameString(selGroup->name, "allTables")) { char *selDb = findSelDb(); struct slName *dbList = getDbListForGenome(), *db; hPrintf("database:\n"); hPrintf("\n"); } else { boolean allTracks = sameString(selGroup->name, "allTracks"); hPrintf("Track:\n"); hPrintf("\n"); } hPrintf("\n"); return selTrack; } char *unsplitTableName(char *table) /* Convert chr*_name to name */ { if (startsWith("chr", table)) { char *s = strrchr(table, '_'); if (s != NULL) { table = s + 1; } } return table; } struct slName *tablesForDb(char *db) /* Find tables associated with database. */ { boolean isGenomeDb = sameString(db, database); struct sqlConnection *conn = hAllocConn(db); struct slName *raw, *rawList = sqlListTables(conn); struct slName *cooked, *cookedList = NULL; struct hash *uniqHash = newHash(0); hFreeConn(&conn); for (raw = rawList; raw != NULL; raw = raw->next) { if (cartTrackDbIsAccessDenied(db, raw->name)) continue; if (isGenomeDb) { /* Deal with tables split across chromosomes. */ char *root = unsplitTableName(raw->name); if (cartTrackDbIsAccessDenied(db, root)) continue; if (!hashLookup(uniqHash, root)) { hashAdd(uniqHash, root, NULL); cooked = slNameNew(root); slAddHead(&cookedList, cooked); } } else { char dbTable[256]; safef(dbTable, sizeof(dbTable), "%s.%s", db, raw->name); cooked = slNameNew(dbTable); slAddHead(&cookedList, cooked); } } hashFree(&uniqHash); slFreeList(&rawList); slSort(&cookedList, slNameCmp); return cookedList; } char *showTableField(struct trackDb *track, char *varName, boolean useJoiner) /* Show table control and label. */ { struct slName *name, *nameList = NULL; char *selTable; if (track == NULL) nameList = tablesForDb(findSelDb()); else nameList = cartTrackDbTablesForTrack(database, track, useJoiner); /* Get currently selected table. If it isn't in our list * then revert to first in list. */ selTable = cartUsualString(cart, varName, nameList->name); if (!slNameInListUseCase(nameList, selTable)) selTable = nameList->name; /* Print out label and drop-down list. */ hPrintf("Table: "); hPrintf("\n"); if (!trackHubDatabase(database)) { char *restrictDate = encodeRestrictionDateDisplay(database,selTdb); if (restrictDate) { hPrintf("restricted until: %s", ENCODE_DATA_RELEASE_POLICY, restrictDate); freeMem(restrictDate); } } return selTable; } struct outputType /* Info on an output type. */ { struct outputType *next; char *name; /* Symbolic name of type. */ char *label; /* User visible label. */ }; static void showOutDropDown(struct outputType *otList, struct outputType *otDefault) /* Display output drop-down. */ { struct outputType *ot; char *outputType = cartUsualString(cart, hgtaOutputType, otList->name); if (otDefault != NULL && otDefault != otList) { boolean otInOtList = FALSE; for (ot = otList; ot != NULL; ot = ot->next) if (sameString(ot->name, outputType)) { otInOtList = TRUE; break; } if (! otInOtList) outputType = otDefault->name; } hPrintf("\n"); hPrintf(" "); hPrintf("
", trackHubSkipHubName(database)); hPrintf(" "); hPrintf(" "); // we should make an hgTables.js one day, this is ugly jsInline("function checkOutputNotes(event) {\n" "var outType=document.getElementById('outputTypeDropdown').value;\n" "if (outType==='gff')\n" " document.getElementById('gffNote').style.display='';\n" "else if (outType==='wigData')\n" " document.getElementById('wigNote').style.display='';\n" "else\n" " $('.outputNote').hide();\n" // a lot shorter with Jquery than without "}\n" "$(document).ready(checkOutputNotes);\n" ); jsAddEventForId("change", "outputTypeDropdown", "checkOutputNotes"); jsInline("function checkSnpTablesNote(event) {\n" "var trackName = document.getElementById('hgta_track').value;\n" "if (trackName.startsWith('dbSnp') || trackName.startsWith('snp') || trackName.startsWith('gnomad'))\n" " document.getElementById('snpTablesNote').style.display='';\n" "else\n" " document.getElementById('snpTablesNote').style.display='none';\n" "}\n" "$(document).ready(checkSnpTablesNote);\n" ); jsAddEventForId("change", "outputTypeDropdown", "checkSnpTablesNote"); jsInlineF("function checkForCsv(event) {\n" "var outputType = document.getElementById('outputTypeDropdown').value;\n" "if (outputType === 'primaryTable' || outputType === 'selectedFields') {\n" " document.getElementById('%s').parentElement.style.display='';\n" " document.getElementById('excelOutNote').style.display='';\n" "} else {\n" " document.getElementById('%s').parentElement.style.display='none';\n" " document.getElementById('excelOutNote').style.display='none';\n" "}\n" "}\n" "$(document).ready(checkForCsv);\n" , hgtaOutSep, hgtaOutSep); jsAddEventForId("change", "outputTypeDropdown", "checkForCsv"); /* * Code to add in the interactive tutorial*/ if (cfgOptionBooleanDefault("showTutorial", TRUE)) { jsIncludeFile("shepherd.min.js", NULL); webIncludeResourceFile("shepherd.css"); jsIncludeFile("jquery.js", NULL); jsIncludeFile("jquery-ui.js", NULL); webIncludeResourceFile("jquery-ui.css"); jsIncludeFile("tutorialPopup.js", NULL); jsIncludeFile("tableBrowserTutorial.js",NULL); if (sameOk(cgiOptionalString("startTutorial"), "true")) { jsInline("var startTableBrowserOnLoad = true;"); jsInline("tableBrowserTour.start();"); } } if (!cfgOptionBooleanDefault("hgta.disableSendOutput", FALSE)) { hPrintf(" Send output to "); struct dyString *dy = dyStringNew(256); dyStringAppend(dy, "document.getElementById('checkboxGreat').checked=false;"); if (isGenomeSpaceEnabled()) dyStringAppend(dy, "document.getElementById('checkboxGenomeSpace').checked=false;"); dyStringAppend(dy, "return true;"); cgiMakeCheckBoxWithId("sendToGalaxy", doGalaxy(), "checkboxGalaxy"); jsOnEventById("click", "checkboxGalaxy", dy->string); hPrintf("Galaxy\n"); nbSpaces(2); cgiMakeCheckBoxWithId("sendToGreat", doGreat(), "checkboxGreat"); jsOnEventById("click", "checkboxGreat", "return onSelectGreat();"); hPrintf(" GREAT"); if (isGenomeSpaceEnabled()) { nbSpaces(2); cgiMakeCheckBoxWithId("sendToGenomeSpace", doGenomeSpace(), "checkboxGenomeSpace"); jsOnEventById("click", "checkboxGenomeSpace", "document.getElementById('checkboxGreat').checked=false;" "document.getElementById('checkboxGalaxy').checked=false; return true;"); hPrintf(" GenomeSpace"); } } hPrintf("\n"); } struct outputType otAllFields = { NULL, outPrimaryTable,"All fields from selected table", }; struct outputType otSelected = { NULL, outSelectedFields, "Selected fields from primary and related tables", }; struct outputType otSequence = { NULL, outSequence, "Sequence", }; struct outputType otPal = { NULL, outPalOptions, "CDS FASTA alignment from multiple alignment", }; struct outputType otGff = { NULL, outGff, "GTF - gene transfer format (limited)", }; struct outputType otBed = { NULL, outBed, "BED - browser extensible data", }; struct outputType otCustomTrack = { NULL, outCustomTrack, "Custom track", }; struct outputType otHyperlinks = { NULL, outHyperlinks, "Hyperlinks to Genome Browser", }; struct outputType otWigData = { NULL, outWigData, "Data points", }; struct outputType otWigBed = { NULL, outWigBed, "Bed format", }; struct outputType otMaf = { NULL, outMaf, "MAF - multiple alignment format", }; struct outputType otChromGraphData = { NULL, outChromGraphData, "Data points", }; struct outputType otMicroarrayNames = { NULL, outMicroarrayNames, "Microarray names", }; struct outputType otMicroarrayGroupings = { NULL, outMicroarrayGroupings, "Microarray groupings", }; static void showOutputTypeRow(boolean isWig, boolean isBedGr, boolean isPositional, boolean isMaf, boolean isChromGraphCt, boolean isPal, boolean isMicroarray, boolean isHalSnake) /* Print output line. */ { struct outputType *otList = NULL, *otDefault = NULL; boolean bedifiedOnly = (anySubtrackMerge(database, curTable) || anyIntersection()); hPrintf("Clade:\n");
printCladeListHtml(hGenome(database), "change", onChangeClade());
nbSpaces(3);
hPrintf("Genome:\n");
printGenomeListForCladeHtml(database, "change", onChangeOrg());
}
else
{
hPrintf(" Genome:\n");
printGenomeListHtml(database, "change", onChangeOrg());
}
nbSpaces(3);
hPrintf("Assembly:\n");
printAssemblyListHtml(database, "change", onChangeDb());
hPrintf(" ");
selGroup = showGroupField(hgtaGroup, "change", onChangeGroupOrTrack(), conn, hAllowAllTables());
nbSpaces(3);
curTrack = showTrackField(selGroup, hgtaTrack, "change", onChangeGroupOrTrack(), FALSE);
nbSpaces(3);
hPrintf(" ");
curTable = showTableField(curTrack, hgtaTable, TRUE);
if (isHubTrack(curTable) || hashFindVal(fullTableToTdbHash, curTable) != NULL) /* In same database */
{
hti = getHti(database, curTable, conn);
isPositional = htiIsPositional(hti);
}
isLongTabix = isLongTabixTable( curTable);
isBam = isBamTable(curTable);
isHic = isHicTable(curTable);
isVcf = isVcfTable(curTable, NULL);
isWig = isWiggle(database, curTable);
if (isBigWigTable(curTable))
{
isPositional = TRUE;
isWig = TRUE;
}
isHalSnake = isHalTable( curTable);
isMaf = isMafTable(database, curTrack, curTable);
isBedGr = isBedGraph(curTable);
isArray = isMicroarray(curTrack, curTable);
struct trackDb *tdb = findTdbForTable(database, curTrack, curTable, ctLookupName);
isPal = isPalCompatible(conn, tdb, curTable);
nbSpaces(1);
if (isCustomTrack(curTable))
{
isChromGraphCt = isChromGraph(tdb);
}
cgiMakeButton(hgtaDoSchema, "Data format description");
hPrintf(" Region:\n");
/* If regionType not allowed force it to "genome". */
if ((sameString(regionType, hgtaRegionTypeUserRegions) &&
userRegionsFileName() == NULL) ||
(sameString(regionType, hgtaRegionTypeEncode) && !doEncode))
regionType = hgtaRegionTypeGenome;
// Is "genome" is not allowed because of tdb 'tableBrowser noGenome'?
boolean disableGenome = ((curTrack && cartTrackDbIsNoGenome(database, curTrack->table)) ||
(curTable && cartTrackDbIsNoGenome(database, curTable)));
// If "genome" is selected but not allowed, force it to "range":
if (sameString(regionType, hgtaRegionTypeGenome) && disableGenome)
regionType = hgtaRegionTypeRange;
jsTrackingVar("regionType", regionType);
if (disableGenome)
{
makeRegionButtonExtraHtml(hgtaRegionTypeGenome, regionType, "DISABLED");
hPrintf(" genome (unavailable for selected track)"
" ");
}
else
{
makeRegionButton(hgtaRegionTypeGenome, regionType);
hPrintf(" Genome ");
}
if (doEncode)
{
makeRegionButton(hgtaRegionTypeEncode, regionType);
hPrintf(" ENCODE Pilot regions ");
}
makeRegionButton(hgtaRegionTypeRange, regionType);
hPrintf(" Position ");
hPrintf("\n",
hgtaRange, hgtaRange, range);
jsOnEventById("focus", hgtaRange,
jsRadioUpdate(hgtaRegionType, "regionType", "range"));
cgiMakeButton(hgtaDoLookupPosition, "Lookup");
hPrintf(" ");
if (userRegionsFileName() != NULL)
{
makeRegionButton(hgtaRegionTypeUserRegions, regionType);
hPrintf(" Defined regions ");
cgiMakeButton(hgtaDoSetUserRegions, "Change");
hPrintf(" ");
cgiMakeButton(hgtaDoClearUserRegions, "Clear");
}
else
cgiMakeButton(hgtaDoSetUserRegions, "Define regions");
hPrintf(" ");
hPrintf("");
printNoGenomeWarning(curTrack);
hPrintf(" | Identifiers (names/accessions):\n");
cgiMakeButton(hgtaDoPasteIdentifiers, "Paste list");
hPrintf(" ");
cgiMakeButton(hgtaDoUploadIdentifiers, "Upload list");
if (identifierFileName() != NULL)
{
hPrintf(" ");
cgiMakeButton(hgtaDoClearIdentifiers, "Clear list");
}
hPrintf(" Filter:\n");
if (anyFilter())
{
cgiMakeButton(hgtaDoFilterPage, "Edit");
hPrintf(" ");
cgiMakeButton(hgtaDoClearFilter, "Clear");
if (isWig || isBedGr)
wigShowFilter(conn);
}
else
{
cgiMakeButton(hgtaDoFilterPage, "Create");
}
hPrintf(" | Subtrack merge:\n");
if (anySubtrackMerge(database, curTable))
{
cgiMakeButton(hgtaDoSubtrackMergePage, "Edit");
hPrintf(" ");
cgiMakeButton(hgtaDoClearSubtrackMerge, "Clear");
}
else
{
cgiMakeButton(hgtaDoSubtrackMergePage, "Create");
}
hPrintf(" | Intersection with %s:\n",
cartString(cart, hgtaIntersectTable));
cgiMakeButton(hgtaDoIntersectPage, "Edit");
hPrintf(" ");
cgiMakeButton(hgtaDoClearIntersect, "Clear");
hPrintf(" | Intersection:\n");
cgiMakeButton(hgtaDoIntersectPage, "Create");
+ hPrintf("Need to intersect on position?");
+ printInfoIcon("Want to intersect two tables on their chrom-start-end fields and keep all other fields from both tables? For exampe, you selec one track with SNPs and want to overlap against enhancers and need to output both the SNP and the enhancer information, our Data Annotation Integrator is the right tool for you");
hPrintf(" | Correlation:\n");
if (differentWord(table2, "none") && strlen(table2) && ! isNoGenomeDisabled(database, table2))
{
struct grp *groupList = fullGroupList;
struct grp *selGroup = findSelectedGroup(groupList, hgtaCorrelateGroup);
struct trackDb *tdb2 = findSelectedTrack(fullTrackList, selGroup,hgtaCorrelateTrack);
if (tdbIsComposite(tdb2))
{
struct slRef *tdbRefList = trackDbListGetRefsToDescendantLeaves(tdb2->subtracks);
struct slRef *tdbRef;
for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next)
{
struct trackDb *subTdb = tdbRef->val;
if (sameString(table2, subTdb->table))
{
tdb2 = subTdb;
break;
}
}
slFreeList(&tdbRefList);
}
cgiMakeButton(hgtaDoCorrelatePage, "Calculate");
cgiMakeButton(hgtaDoClearCorrelate, "Clear");
if (tdb2 && tdb2->shortLabel)
hPrintf(" (with: %s)", tdb2->shortLabel);
#ifdef NOT_YET
/* debugging dbg vvvvv */
if (curTrack && curTrack->type) /* dbg */
{
hPrintf(" | (debug: '%s', '%s(%s)')", curTrack->type, tdb2->type, table2); } /* debugging debug ^^^^^ */ #endif } else cgiMakeButton(hgtaDoCorrelatePage, "Create"); hPrintf(" \n");
hPrintf(" | Output filename: ");
cgiMakeTextVar(hgtaOutFileName, fileName, 29);
hPrintf(" ( leave blank to keep output in browser)\n");
hPrintf("Output field separator: ");
// tab or csv output
cgiMakeRadioButton(hgtaOutSep, outTab, sameWord(outTab, fieldSep));
hPrintf(" tsv (tab-separated)  ");
cgiMakeRadioButton(hgtaOutSep, outCsv, sameWord(outCsv, fieldSep));
hPrintf(" csv (for excel) ");
hPrintf(" | \n");
hPrintf("File type returned: ");
cgiMakeRadioButton(hgtaCompressType, textOutCompressNone,
sameWord(textOutCompressNone, compressType));
hPrintf(" Plain text ");
cgiMakeRadioButton(hgtaCompressType, textOutCompressGzip,
sameWord(textOutCompressGzip, compressType));
hPrintf(" Gzip compressed");
hPrintf(" | |