1af908554ee6f4607ebc2996da5f50da872298a3 braney Mon Mar 23 07:56:44 2015 -0700 rewind check-in of ancient version of simpleTracks.c that git decided I wanted to check in. diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index 58e8c43..c58b312 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -1,28 +1,32 @@ /* infrastructure -- Code shared by all tracks. Separating this out from * hgTracks.c allows a standalone main to make track images. */ +/* Copyright (C) 2014 The Regents of the University of California + * See README in this or parent directory for licensing information. */ + /* NOTE: This code was imported from hgTracks.c 1.1469, May 19 2008, * so a lot of revision history has been obscured. To see code history * from before this file was created, run this: * cvs ann -r 1.1469 hgTracks.c | less +Gp */ #include "common.h" #include "spaceSaver.h" #include "portable.h" #include "bed.h" +#include "basicBed.h" #include "psl.h" #include "web.h" #include "hdb.h" #include "hgFind.h" #include "hCommon.h" #include "hgColors.h" #include "trackDb.h" #include "bedCart.h" #include "wiggle.h" #include "lfs.h" #include "grp.h" #include "chromColors.h" #include "hgTracks.h" #include "subText.h" #include "cds.h" @@ -37,30 +41,31 @@ #ifndef GBROWSE #include "encode.h" #include "expRatioTracks.h" #include "hapmapTrack.h" #include "retroGene.h" #include "switchGear.h" #include "variation.h" #include "wiki.h" #include "wormdna.h" #include "aliType.h" #include "agpGap.h" #include "cgh.h" #include "bactigPos.h" #include "genePred.h" #include "genePredReader.h" +#include "gencodeTracks.h" #include "isochores.h" #include "spDb.h" #include "simpleRepeat.h" #include "cpgIsland.h" #include "gcPercent.h" #include "genomicDups.h" #include "mapSts.h" #include "est3.h" #include "exoFish.h" #include "roughAli.h" #include "snp.h" #include "rnaGene.h" #include "fishClones.h" #include "stsMarker.h" #include "stsMap.h" @@ -86,55 +91,55 @@ #include "altGraph.h" #include "altGraphX.h" #include "geneGraph.h" #include "genMapDb.h" #include "genomicSuperDups.h" #include "celeraDupPositive.h" #include "celeraCoverage.h" #include "simpleNucDiff.h" #include "tfbsCons.h" #include "tfbsConsSites.h" #include "itemAttr.h" #include "encode.h" #include "variation.h" #include "estOrientInfo.h" #include "versionInfo.h" -#include "gencodeIntron.h" #include "retroGene.h" #include "switchGear.h" #include "dless.h" #include "liftOver.h" #include "hgConfig.h" #include "gv.h" #include "gvUi.h" #include "protVar.h" #include "oreganno.h" #include "oregannoUi.h" #include "pgSnp.h" #include "bedDetail.h" #include "bed12Source.h" #include "dbRIP.h" #include "wikiLink.h" #include "wikiTrack.h" #include "dnaMotif.h" #include "hapmapTrack.h" #include "omicia.h" #include "nonCodingUi.h" #include "transMapTracks.h" #include "retroTracks.h" #include "pcrResult.h" #include "variome.h" +#include "pubsTracks.h" #endif /* GBROWSE */ #ifdef LOWELAB #include "loweLabTracks.h" #include "rnaPLFoldTrack.h" #endif /* LOWELAB */ #ifdef LOWELAB_WIKI #include "wiki.h" #endif /* LOWELAB_WIKI */ #define CHROM_COLORS 26 int colorBin[MAXPIXELS][256]; /* count of colors for each pixel for each color */ /* Declare our color gradients and the the number of colors in them */ Color shadesOfGreen[EXPR_DATA_SHADES]; @@ -153,59 +158,60 @@ Color darkBlueColor = 0; Color greenColor = 0; Color darkGreenColor = 0; boolean exprBedColorsMade = FALSE; /* Have the shades of Green, Red, and Blue been allocated? */ int maxRGBShade = EXPR_DATA_SHADES - 1; Color chromColor[CHROM_COLORS+1]; /* Declare colors for chromosome coloring, +1 for unused chrom 0 color */ /* Have the 3 shades of 8 chromosome colors been allocated? */ boolean chromosomeColorsMade = FALSE; int z; int maxCount; int bestColor; -int maxItemsInFullTrack = 250; /* Maximum number of items displayed in full */ +int maxItemsInFullTrack = 1000; /* Maximum number of items displayed in full */ int maxItemsToUseOverflowDefault = 10000; /* # of items to allow overflow mode*/ /* These variables persist from one incarnation of this program to the * next - living mostly in the cart. */ char *chromName; /* Name of chromosome sequence . */ char *database; /* Name of database we're using. */ char *organism; /* Name of organism we're working on. */ int winStart; /* Start of window in sequence. */ int winEnd; /* End of window in sequence. */ char *position = NULL; /* Name of position. */ int trackTabWidth = 11; int leftLabelWidthDefaultChars = 17; /* default number of characters allowed for left label */ int leftLabelWidthChars = 17; /* number of characters allowed for left label */ int insideX; /* Start of area to draw track in in pixels. */ int insideWidth; /* Width of area to draw tracks in in pixels. */ int leftLabelX; /* Start of area to draw left labels on. */ int leftLabelWidth; /* Width of area to draw left labels on. */ float basesPerPixel = 0; /* bases covered by a pixel; a measure of zoom */ boolean zoomedToBaseLevel; /* TRUE if zoomed so we can draw bases. */ boolean zoomedToCodonLevel; /* TRUE if zoomed so we can print codons text in genePreds*/ boolean zoomedToCdsColorLevel; /* TRUE if zoomed so we can color each codon*/ boolean withLeftLabels = TRUE; /* Display left labels? */ boolean withIndividualLabels = TRUE; /* print labels on item-by-item basis (false to skip) */ boolean withCenterLabels = TRUE; /* Display center labels? */ boolean withGuidelines = TRUE; /* Display guidelines? */ boolean withNextExonArrows = FALSE; /* Display next exon navigation buttons near center labels? */ +boolean withExonNumbers = FALSE; /* Display exon and intron numbers in mouseOver instead of item name */ boolean revCmplDisp = FALSE; /* reverse-complement display */ boolean measureTiming = FALSE; /* DON'T EDIT THIS -- use CGI param "&measureTiming=." . */ struct track *trackList = NULL; /* List of all tracks. */ struct cart *cart; /* The cart where we keep persistent variables. */ int seqBaseCount; /* Number of bases in sequence. */ int winBaseCount; /* Number of bases in window. */ int maxShade = 9; /* Highest shade in a color gradient. */ Color shadesOfGray[10+1]; /* 10 shades of gray from white to black * Red is put at end to alert overflow. */ Color shadesOfBrown[10+1]; /* 10 shades of brown from tan to tar. */ struct rgbColor brownColor = {100, 50, 0}; struct rgbColor tanColor = {255, 240, 200}; @@ -292,53 +298,65 @@ /* Temporary function until all composite tracks point to their own children */ { return (tdbIsComposite(track->tdb) && track->subtracks != NULL); } Color slightlyLighterColor(struct hvGfx *hvg, Color color) /* Get slightly lighter shade of a color - closer to gray actually */ { struct rgbColor rgbColor = hvGfxColorIxToRgb(hvg, color); rgbColor.r = (rgbColor.r+128)/2; rgbColor.g = (rgbColor.g+128)/2; rgbColor.b = (rgbColor.b+128)/2; return hvGfxFindColorIx(hvg, rgbColor.r, rgbColor.g, rgbColor.b); } +void checkIfWiggling(struct cart *cart, struct track *tg) +/* Check to see if a linkedFeatures track should be drawing as a wiggle. */ +{ +boolean doWiggle = cartOrTdbBoolean(cart, tg->tdb, "doWiggle" , FALSE); +if (doWiggle) + { + tg->drawLeftLabels = wigLeftLabels; + tg->colorShades = shadesOfGray; + tg->mapsSelf = TRUE; + } +} + int packCountRowsOverflow(struct track *tg, int maxCount, boolean withLabels, boolean allowOverflow) /* Return packed height. */ { struct spaceSaver *ss; struct slList *item; MgFont *font = tl.font; int extraWidth = tl.mWidth * 2; long long start, end; double scale = (double)insideWidth/(winEnd - winStart); spaceSaverFree(&tg->ss); ss = tg->ss = spaceSaverNew(0, insideWidth, maxCount); for (item = tg->items; item != NULL; item = item->next) { int baseStart = tg->itemStart(tg, item); int baseEnd = tg->itemEnd(tg, item); if (baseStart < winEnd && baseEnd > winStart) { if (baseStart <= winStart) start = 0; else start = round((double)(baseStart - winStart)*scale); - if (!tg->drawName && withLabels) + if (!tg->drawLabelInBox && !tg->drawName && withLabels) start -= mgFontStringWidth(font, tg->itemName(tg, item)) + extraWidth; if (baseEnd >= winEnd) end = insideWidth; else end = round((baseEnd - winStart)*scale); if (tg->itemRightPixels && withLabels) { end += tg->itemRightPixels(tg, item); if (end > insideWidth) end = insideWidth; } if (start < 0) start = 0; if (spaceSaverAddOverflow(ss, start, end, item, allowOverflow) == NULL) break; @@ -393,30 +411,42 @@ /* Return the maximum number of items to allow overflow indication. */ { int answer = maxItemsToUseOverflowDefault; char *maxItemsString = trackDbSetting(tg->tdb, "maxItemsToOverflow"); if (maxItemsString != NULL) answer = sqlUnsigned(maxItemsString); return answer; } int tgFixedTotalHeightOptionalOverflow(struct track *tg, enum trackVisibility vis, int lineHeight, int heightPer, boolean allowOverflow) /* Most fixed height track groups will use this to figure out the height * they use. */ { +boolean doWiggle = cartOrTdbBoolean(cart, tg->tdb, "doWiggle" , FALSE); +if (doWiggle) + { + struct wigCartOptions *wigCart = tg->wigCartData; + if (tg->wigCartData == NULL) + { + wigCart = wigCartOptionsNew(cart, tg->tdb, 0, NULL ); + tg->wigCartData = (void *) wigCart; + } + return wigTotalHeight(tg, vis); + } + int rows; double maxHeight = maximumTrackHeight(tg); int itemCount = slCount(tg->items); int maxItemsToUseOverflow = maxItemsToOverflow(tg); tg->heightPer = heightPer; tg->lineHeight = lineHeight; /* Note that the maxCount variable passed to packCountRowsOverflow() is tied to the maximum height allowed for a track and influences decisions about when to squish, dense, or overflow a track. If doing overflow try to pack all the items into the maxHeight area or put all the overflow into the last row. If not doing overflow allow the track enough rows to go over the maxHeight (thus if the spaceSaver fills up the total height will be more than maxHeight). @@ -488,82 +518,77 @@ if (orient < 0) return '-'; if (orient > 0) return '+'; return '.'; } struct dyString *uiStateUrlPart(struct track *toggleGroup) /* Return a string that contains all the UI state in CGI var * format. If toggleGroup is non-null the visibility of that * track will be toggled in the string. */ { struct dyString *dy = newDyString(512); -dyStringPrintf(dy, "%s=%u", cartSessionVarName(), cartSessionId(cart)); +dyStringPrintf(dy, "%s=%s", cartSessionVarName(), cartSessionId(cart)); if (toggleGroup != NULL && tdbIsCompositeChild(toggleGroup->tdb)) { int vis = toggleGroup->visibility; struct trackDb *tdbParent = tdbGetComposite(toggleGroup->tdb); char *parentName = tdbParent->track; // Find parent track (as opposed to trackDb) struct track *tgParent =toggleGroup->parent; char *encodedTableName = cgiEncode(parentName); char *view = NULL; boolean setView = subgroupFind(toggleGroup->tdb,"view",&view); if (tgParent!=NULL&& tgParent->visibility != tvHide && tvCompare(tgParent->visibility,vis) > 0) { setView = FALSE; // Must open parent to see opened child vis = tgParent->visibility; } if (vis == tvDense) { if (!toggleGroup->canPack || view != NULL) vis = tvFull; else vis = tvPack; } else if (vis != tvHide) vis = tvDense; if (setView) { - #ifdef SUBTRACK_CFG dyStringPrintf(dy, "&%s=%s", toggleGroup->tdb->parent->track, hStringFromTv(vis)); - #else///ifndef SUBTRACK_CFG - char *encodeView = cgiEncode(view); - dyStringPrintf(dy, "&%s.%s.vis=%s", encodedTableName,encodeView, hStringFromTv(vis)); - freeMem(encodeView); - #endif///ndef SUBTRACK_CFG } else { dyStringPrintf(dy, "&%s=%s", encodedTableName, hStringFromTv(vis)); } subgroupFree(&view); freeMem(encodedTableName); } else { if (toggleGroup != NULL) { int vis = toggleGroup->visibility; char *encodedMapName = cgiEncode(toggleGroup->track); if (vis == tvDense) { - if(!toggleGroup->canPack || (tdbIsComposite(toggleGroup->tdb) && subgroupingExists(toggleGroup->tdb,"view"))) + if (!toggleGroup->canPack + || (tdbIsComposite(toggleGroup->tdb) && subgroupingExists(toggleGroup->tdb,"view"))) vis = tvFull; else vis = tvPack; } else if (vis == tvFull || vis == tvPack || vis == tvSquish) vis = tvDense; dyStringPrintf(dy, "&%s=%s", encodedMapName, hStringFromTv(vis)); freeMem(encodedMapName); } } return dy; } boolean isWithCenterLabels(struct track *track) /* Cases: only TRUE when global withCenterLabels is TRUE @@ -576,31 +601,33 @@ { char *centerLabelsDense = trackDbSetting(track->tdb, "centerLabelsDense"); if (centerLabelsDense) { return sameWord(centerLabelsDense, "on"); } } return withCenterLabels; } boolean isCenterLabelConditionallySeen(struct track *track) // returns FALSE if track and prevTrack have same parent, and are both dense subtracks { if (isCenterLabelConditional(track)) { - if (track->prevTrack && track->parent == track->prevTrack->parent && isCenterLabelConditional(track->prevTrack)) + if (track->prevTrack + && track->parent == track->prevTrack->parent + && isCenterLabelConditional(track->prevTrack)) return FALSE; } return isWithCenterLabels(track); } void mapStatusMessage(char *format, ...) /* Write out stuff that will cause a status message to * appear when the mouse is over this box. */ { va_list(args); va_start(args, format); hPrintf(" TITLE=\""); hvPrintf(format, args); hPutc('"'); va_end(args); @@ -623,81 +650,85 @@ if (extra != NULL) { dyStringAppend(ui, "&"); dyStringAppend(ui, extra); } if (chrom == NULL) { chrom = chromName; start = winStart; end = winEnd; } if (theImgBox && curImgTrack) { char link[512]; - safef(link,sizeof(link),"%s?position=%s:%d-%d&%s",hgTracksName(), chrom, start+1, end, ui->string); // NOTE: position may need removing due to portal + safef(link,sizeof(link),"%s?position=%s:%d-%d&%s", // NOTE: position may need removing + hgTracksName(), chrom, start+1, end, ui->string); // due to portal if (!revCmplDisp && x < insideX) // Do not toggle on side label! { width -= (insideX+1 - x); if (width <= 1) { freeDyString(&ui); return; } x = insideX+1; } else if (revCmplDisp && (x+width) >= insideWidth) { width -= (x+width) - insideWidth + 1; if (width <= 1) { freeDyString(&ui); return; } } //#ifdef IMAGEv2_SHORT_MAPITEMS // if (x < insideX && x+width > insideX) - // warn("mapBoxReinvoke(%s) map item spanning slices. LX:%d TY:%d RX:%d BY:%d link:[%s]",hStringFromTv(toggleGroup->visibility),x, y, x+width, y+height, link); + // warn("mapBoxReinvoke(%s) map item spanning slices. LX:%d TY:%d RX:%d BY:%d link:[%s]", + // hStringFromTv(toggleGroup->visibility),x, y, x+width, y+height, link); //#endif//def IMAGEv2_SHORT_MAPITEMS - imgTrackAddMapItem(curImgTrack,link,(char *)(message != NULL?message:NULL),x, y, x+width, y+height, - track ? track->track : NULL); + imgTrackAddMapItem(curImgTrack,link,(char *)(message != NULL?message:NULL),x, y, x+width, + y+height, track ? track->track : NULL); } else { hPrintf("<AREA SHAPE=RECT COORDS=\"%d,%d,%d,%d\" ", x, y, x+width, y+height); hPrintf("HREF=\"%s?position=%s:%d-%d", hgTracksName(), chrom, start+1, end); hPrintf("&%s\"", ui->string); if (message != NULL) mapStatusMessage("%s", message); hPrintf("%s>\n", dyStringContents(id)); } freeDyString(&ui); freeDyString(&id); } void mapBoxToggleVis(struct hvGfx *hvg, int x, int y, int width, int height, struct track *curGroup) /* Print out image map rectangle that would invoke this program again. * program with the current track expanded. */ { char buf[256]; if (tdbIsCompositeChild(curGroup->tdb)) - safef(buf, sizeof(buf),"Click to alter the display density of %s and similar subtracks", curGroup->shortLabel); + safef(buf, sizeof(buf),"Click to alter the display density of %s and similar subtracks", + curGroup->shortLabel); else if (tdbIsComposite(curGroup->tdb)) - safef(buf, sizeof(buf),"Click to alter the maximum display mode density for all %s subtracks", curGroup->shortLabel); + safef(buf, sizeof(buf),"Click to alter the maximum display mode density for all %s subtracks", + curGroup->shortLabel); else safef(buf, sizeof(buf),"Click to alter the display density of %s", curGroup->shortLabel); mapBoxReinvoke(hvg, x, y, width, height, curGroup, TRUE, NULL, 0, 0, buf, NULL); } void mapBoxJumpTo(struct hvGfx *hvg, int x, int y, int width, int height, struct track *track, char *newChrom, int newStart, int newEnd, char *message) /* Print out image map rectangle that would invoke this program again * at a different window. */ { mapBoxReinvoke(hvg, x, y, width, height, track, FALSE, newChrom, newStart, newEnd, message, NULL); } @@ -720,55 +751,55 @@ char *extra) /* Print out image map rectangle that would invoke the hgc (human genome click) * program. */ { struct dyString *id = dyStringNew(0); if (x < 0) x = 0; x = hvGfxAdjXW(hvg, x, width); int xEnd = x+width; int yEnd = y+height; dyStringPrintf(id, " id='%s'", track); if (x < xEnd) { char *encodedItem = cgiEncode(item); char *encodedTrack = cgiEncode(track); - if (theImgBox && curImgTrack) { char link[512]; if (directUrl) { safef(link,sizeof(link),directUrl, item, chromName, start, end, encodedTrack, database); if (withHgsid) safef(link+strlen(link),sizeof(link)-strlen(link),"&%s", cartSidUrlString(cart)); } else { safef(link,sizeof(link),"%s&c=%s&o=%d&t=%d&g=%s&i=%s", hgcNameAndSettings(), chromName, start, end, encodedTrack, encodedItem); // NOTE: chopped out winStart/winEnd } if (extra != NULL) safef(link+strlen(link),sizeof(link)-strlen(link),"&%s", extra); - // Add map item to currnent map (TODO: pass in map) + // Add map item to current map (TODO: pass in map) #ifdef IMAGEv2_SHORT_MAPITEMS - if(!revCmplDisp && x < insideX && xEnd > insideX) // Why does insideX=118 in reverse complement?? + if (!revCmplDisp && x < insideX && xEnd > insideX) x = insideX; else if (revCmplDisp && x < insideWidth && xEnd > insideWidth) xEnd = insideWidth - 1; #endif//def IMAGEv2_SHORT_MAPITEMS - imgTrackAddMapItem(curImgTrack,link,(char *)(statusLine!=NULL?statusLine:NULL),x, y, xEnd, yEnd, track); + imgTrackAddMapItem(curImgTrack,link,(char *)(statusLine!=NULL?statusLine:NULL), + x, y, xEnd, yEnd, track); } else { hPrintf("<AREA SHAPE=RECT COORDS=\"%d,%d,%d,%d\" ", x, y, xEnd, yEnd); if (directUrl) { hPrintf("HREF=\""); hPrintf(directUrl, item, chromName, start, end, encodedTrack, database); if (withHgsid) hPrintf("&%s", cartSidUrlString(cart)); } else { hPrintf("HREF=\"%s&c=%s&o=%d&t=%d&g=%s&i=%s&c=%s&l=%d&r=%d&db=%s&pix=%d", hgcNameAndSettings(), chromName, start, end, encodedTrack, encodedItem, @@ -931,32 +962,32 @@ } else { /* restore char for unaligned sequence to lower case */ if (tolower(cBuf[0]) == tolower(UNALIGNED_SEQ)) cBuf[0] = UNALIGNED_SEQ; /* display bases */ hvGfxTextCentered(hvg, x1+x, y, x2-x1, height, clr, font, cBuf); } } freez(&inMotif); } void spreadAlignStringProt(struct hvGfx *hvg, int x, int y, int width, int height, - Color color, MgFont *font, char *text, - char *match, int count, bool dots, bool isCodon, int seqStart, int offset) + Color color, MgFont *font, char *text, char *match, int count, + bool dots, bool isCodon, int seqStart, int offset) /* Draw evenly spaced letters in string for protein sequence. * For multiple alignments, * supply a non-NULL match string, and then matching letters will be colored * with the main color, mismatched letters will have alt color (or * matching letters with a dot, and mismatched bases with main color if this * option is selected). * Draw a vertical bar in orange where sequence lacks gaps that * are in reference sequence (possible insertion) -- this is indicated * by an escaped insert count in the sequence. The escape char is backslash. * The count param is the number of bases to print, not length of * the input line (text) */ { char cBuf[2] = ""; int i,j,textPos=0; int x1, x2, xx1, xx2; @@ -1090,33 +1121,32 @@ } else { hvGfxBox(hvg, xx1+x, y, xx2-xx1, height, color2); } /* display AA */ hvGfxTextCentered(hvg, x1+x, y, x2-x1, height, clr, font, cBuf); } } } } freez(&inMotif); } -void spreadBasesString(struct hvGfx *hvg, int x, int y, int width, - int height, Color color, MgFont *font, - char *s, int count, bool isCodon) +void spreadBasesString(struct hvGfx *hvg, int x, int y, int width, int height, Color color, + MgFont *font, char *s, int count, bool isCodon) /* Draw evenly spaced letters in string. */ { spreadAlignString(hvg, x, y, width, height, color, font, s, NULL, count, FALSE, isCodon); } void drawScaledBox(struct hvGfx *hvg, int chromStart, int chromEnd, double scale, int xOff, int y, int height, Color color) /* Draw a box scaled from chromosome to window coordinates. * Get scale first with scaleForPixels. */ { int x1 = round((double)(chromStart-winStart)*scale) + xOff; int x2 = round((double)(chromEnd-winStart)*scale) + xOff; int w = x2-x1; if (w < 1) @@ -1161,51 +1191,95 @@ blendCount = maxCount; } } maxCount = binCount; maxColor = col; } } if (blendCount >= maxCount) maxColor = blendColor; } if (w < 1) w = 1; hvGfxBox(hvg, x1, y, w, height, maxColor); } +void drawScaledBoxSampleLabel(struct hvGfx *hvg, + int chromStart, int chromEnd, double scale, + int xOff, int y, int height, Color color, MgFont *font, char *label) +/* Draw a box scaled from chromosome to window coordinates and draw a label onto it. + * Lots of code copied from drawScaledBoxSample */ +{ +//int i; +int x1, x2, w; +x1 = round((double)(chromStart-winStart)*scale) + xOff; +x2 = round((double)(chromEnd-winStart)*scale) + xOff; + +if (x2 >= MAXPIXELS) + x2 = MAXPIXELS - 1; + +if (x2 < xOff) + x2 = xOff; +if (x2 > xOff+insideWidth) + x2 = xOff+insideWidth; +if (x1 < xOff) + x1 = xOff; +if (x1 > xOff+insideWidth) + x1 = xOff+insideWidth; +w = x2-x1; +if (w < 1) + w = 1; +hvGfxBox(hvg, x1, y, w, height, color); + +char *shortLabel = cloneString(label); +/* calculate how many characters we can squeeze into the box */ +int charsInBox = w / mgFontCharWidth(font, 'm'); +if (charsInBox > 4) + { + if (charsInBox < strlen(label)) + strcpy(shortLabel+charsInBox-3, "..."); + Color labelColor = hvGfxContrastingColor(hvg, color); + hvGfxTextCentered(hvg, x1, y, w, height, labelColor, font, shortLabel); + } +} + void drawScaledBoxSample(struct hvGfx *hvg, int chromStart, int chromEnd, double scale, int xOff, int y, int height, Color color, int score) /* Draw a box scaled from chromosome to window coordinates. */ { //int i; int x1, x2, w; -x1 = round((double)(chromStart-winStart)*scale) + xOff; -x2 = round((double)(chromEnd-winStart)*scale) + xOff; +int ourStart = chromStart; +if (ourStart < winStart) + ourStart = winStart; +int ourEnd = chromEnd; +if (ourEnd > winEnd) + ourEnd = winEnd; +x1 = round((double)(ourStart-winStart)*scale) + xOff; +x2 = round((double)(ourEnd-winStart)*scale) + xOff; if (x2 >= MAXPIXELS) x2 = MAXPIXELS - 1; w = x2-x1; if (w < 1) w = 1; hvGfxBox(hvg, x1, y, w, height, color); } -void filterItems(struct track *tg, - boolean (*filter)(struct track *tg, void *item), +void filterItems(struct track *tg, boolean (*filter)(struct track *tg, void *item), char *filterType) /* Filter out items from track->itemList. */ { struct slList *newList = NULL, *oldList = NULL, *el, *next; boolean exclude = FALSE; boolean color = FALSE; enum trackVisibility vis = tvHide; if (sameWord(filterType, "none")) return; if (sameWord(filterType, "include")) exclude = FALSE; else if (sameWord(filterType, "exclude")) exclude = TRUE; @@ -1265,30 +1339,44 @@ int linkedFeaturesCmp(const void *va, const void *vb) /* Compare to sort based on start. */ { const struct linkedFeatures *a = *((struct linkedFeatures **)va); const struct linkedFeatures *b = *((struct linkedFeatures **)vb); return a->start - b->start; } char *linkedFeaturesName(struct track *tg, void *item) /* Return name of item. */ { struct linkedFeatures *lf = item; return lf->name; } +char *linkedFeaturesNameField1(struct track *tg, void *item) +/* return part before first space in item name */ +{ +struct linkedFeatures *lf = item; +return cloneFirstWord(lf->name); +} + +char *linkedFeaturesNameNotField1(struct track *tg, void *item) +/* return part after first space in item name */ +{ +struct linkedFeatures *lf = item; +return cloneNotFirstWord(lf->name); +} + void linkedFeaturesFreeList(struct linkedFeatures **pList) /* Free up a linked features list. */ { struct linkedFeatures *lf; for (lf = *pList; lf != NULL; lf = lf->next) { slFreeList(&lf->components); slFreeList(&lf->codons); } slFreeList(pList); } void linkedFeaturesFreeItems(struct track *tg) /* Free up linkedFeaturesTrack items. */ { @@ -1381,39 +1469,39 @@ differentString(cartString(cart,gvSrcString[cnt]), "0") && sameString(gvSrcDbValue[cnt], srcTxt)) { return FALSE; } } return TRUE; } boolean gvFilterDA(struct gv *el) /* Check to see if this element should be excluded (disease association attribute) */ { int cnt = 0; struct gvAttr *attr = NULL; char query[256]; -char *escId = NULL; +char *id = NULL; struct sqlConnection *conn = hAllocConn(database); if (el->id != NULL) - escId = sqlEscapeString(el->id); + id = el->id; else - escId = sqlEscapeString(el->name); + id = el->name; -safef(query, sizeof(query), "select * from hgFixed.gvAttr where id = '%s' and attrType = 'disease'", escId); +sqlSafef(query, sizeof(query), "select * from hgFixed.gvAttr where id = '%s' and attrType = 'disease'", id); attr = gvAttrLoadByQuery(conn, query); hFreeConn(&conn); if (attr == NULL) { AllocVar(attr); attr->attrVal = cloneString("NULL"); attr->id = NULL; /* so free will work */ attr->attrType = NULL; } for (cnt = 0; cnt < gvFilterDASize; cnt++) { if (cartVarExists(cart, gvFilterDAString[cnt]) && cartString(cart, gvFilterDAString[cnt]) != NULL && differentString(cartString(cart, gvFilterDAString[cnt]), "0") && sameString(gvFilterDADbValue[cnt], attr->attrVal)) @@ -1461,34 +1549,32 @@ } for (el = tg->items; el != NULL; el = el->next) { struct dyString *name = dyStringNew(SMALLDYBUF); labelStarted = FALSE; /* reset for each item */ if (useHgvs) { dyStringAppend(name, el->label); labelStarted = TRUE; } if (useCommon) { char query[256]; char *commonName = NULL; - char *escId = sqlEscapeString(el->name); - safef(query, sizeof(query), "select attrVal from hgFixed.gvAttr where id = '%s' and attrType = 'commonName'", escId); + sqlSafef(query, sizeof(query), "select attrVal from hgFixed.gvAttr where id = '%s' and attrType = 'commonName'", el->name); commonName = sqlQuickString(conn, query); - freeMem(escId); if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; if (commonName != NULL) dyStringAppend(name, commonName); else dyStringAppend(name, " "); } if (useId) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; dyStringAppend(name, el->name); } el->id = el->name; /* reassign ID */ el->name = dyStringCannibalize(&name); @@ -1510,40 +1596,39 @@ if (!cartVarExists(cart, "gvDisclaimer")) { /* display disclaimer and add flag to cart, program exits from here */ gvDisclaimer(); } else if (sameString("Disagree", cartString(cart, "gvDisclaimer"))) { /* hide track, remove from cart so will get option again later */ tg->visibility = tvHide; cartRemove(cart, "gvDisclaimer"); cartSetString(cart, "gvPos", "hide"); return; } /* load as linked list once, outside of loop */ -srcList = gvSrcLoadByQuery(conn, "select * from hgFixed.gvSrc"); +srcList = gvSrcLoadByQuery(conn, "NOSQLINJ select * from hgFixed.gvSrc"); /* load part need from gv table, outside of loop (load in hash?) */ sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset); while ((row = sqlNextRow(sr)) != NULL) { struct gv *details = NULL; - char query[256], *escId; + char query[256]; struct gvPos *el = gvPosLoad(row); - escId = sqlEscapeString(el->name); - safef(query, sizeof(query), "select * from hgFixed.gv where id = '%s'", escId); + sqlSafef(query, sizeof(query), "select * from hgFixed.gv where id = '%s'", el->name); details = gvLoadByQuery(conn2, query); /* searched items are always visible */ if (hgFindMatches != NULL && hashIntValDefault(hgFindMatches, el->name, 0) == 1) slAddHead(&list, el); else if (!gvFilterType(details)) gvPosFree(&el); else if (!gvFilterLoc(details)) gvPosFree(&el); else if (!gvFilterSrc(details, srcList)) gvPosFree(&el); else if (!gvFilterAccuracy(details)) gvPosFree(&el); else if (!gvFilterDA(details)) gvPosFree(&el); else @@ -1590,46 +1675,46 @@ /* reset globals */ chromName = chromNameCopy; winStart = winStartCopy; winEnd = winEndCopy; return list; } boolean oregannoFilterType (struct oreganno *el) /* filter of the type of region from the oregannoAttr table */ { int cnt = 0; struct oregannoAttr *attr = NULL; char query[256]; struct sqlConnection *conn = hAllocConn(database); -safef(query, sizeof(query), "select * from oregannoAttr where id = '%s' and attribute = 'type'", el->id); +sqlSafef(query, sizeof(query), "select * from oregannoAttr where id = '%s' and attribute = 'type'", el->id); attr = oregannoAttrLoadByQuery(conn, query); hFreeConn(&conn); if (attr == NULL) { AllocVar(attr); attr->attrVal = cloneString("NULL"); attr->id = NULL; /* so free will work */ attr->attribute = NULL; } for (cnt = 0; cnt < oregannoTypeSize; cnt++) { - if (!cartVarExists(cart, oregannoTypeString[cnt]) || - (cartString(cart, oregannoTypeString[cnt]) != NULL && - differentString(cartString(cart, oregannoTypeString[cnt]), "0") && - sameString(oregannoTypeDbValue[cnt], attr->attrVal))) + if (!cartVarExists(cart, oregannoTypeString[cnt]) + || ( cartString(cart, oregannoTypeString[cnt]) != NULL + && differentString(cartString(cart, oregannoTypeString[cnt]), "0") + && sameString(oregannoTypeDbValue[cnt], attr->attrVal))) { oregannoAttrFree(&attr); return TRUE; /* include this type */ } } oregannoAttrFree(&attr); return FALSE; } void loadOreganno (struct track *tg) /* loads the oreganno track */ { struct oreganno *list = NULL; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr; @@ -1744,31 +1829,31 @@ void linkedFeaturesNextPrevItem(struct track *tg, struct hvGfx *hvg, void *item, int x, int y, int w, int h, boolean next) /* Draw a mapBox over the arrow-button on an *item already in the window*. */ /* Clicking this will do one of several things: */ { struct linkedFeatures *lf = item; struct simpleFeature *exons = lf->components; struct simpleFeature *exon = exons; char *nextExonText; char *prevExonText; int newWinSize = winEnd - winStart; int bufferToEdge = 0.05 * newWinSize; int newWinStart, newWinEnd; int numExons = 0; int exonIx = 0; struct slRef *exonList = NULL, *ref; -if (startsWith("chain", tg->tdb->type)) +if (startsWith("chain", tg->tdb->type) || startsWith("lrg", tg->tdb->track)) { nextExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "nextExonText", "Next Block"); prevExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "prevExonText", "Prev Block"); } else { nextExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "nextExonText", "Next Exon"); prevExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "prevExonText", "Prev Exon"); } while (exon != NULL) /* Make a stupid list of exons separate from what's given. */ /* It seems like lf->components isn't necessarily sorted. */ { refAdd(&exonList, exon); exon = exon->next; @@ -1776,77 +1861,204 @@ /* Now sort it. */ if (next) slSort(&exonList, exonSlRefCmp); else slSort(&exonList, exonSlRefReverseCmp); numExons = slCount(exonList); for (ref = exonList; ref != NULL; ref = ref->next, exonIx++) { char mouseOverText[256]; boolean bigExon = FALSE; boolean revStrand = (lf->orientation == -1); exon = ref->val; if ((exon->end - exon->start) > (newWinSize - (2 * bufferToEdge))) bigExon = TRUE; if (next && (exon->end > winEnd)) - /* right overhang (but left side of screen in reserve-strand-display) */ + /* right overhang (but left side of screen in reverse-strand-display) */ { if (exon->start < winEnd) { /* not an intron hanging over edge. */ if ((lf->tallEnd > winEnd) && (lf->tallEnd < exon->end) && (lf->tallEnd > exon->start)) linkedFeaturesMoveWinEnd(lf->tallEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); else linkedFeaturesMoveWinEnd(exon->end, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); } else if (bigExon) linkedFeaturesMoveWinStart(exon->start, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); else linkedFeaturesMoveWinEnd(exon->end, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); if (!revStrand) safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", nextExonText, exonIx+1, numExons); else safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", prevExonText, numExons-exonIx, numExons); mapBoxJumpTo(hvg, x, y, w, h, tg, chromName, newWinStart, newWinEnd, mouseOverText); break; } else if (!next && (exon->start < winStart)) /* left overhang */ { if (exon->end > winStart) { - /* not an inron hanging over the edge. */ + /* not an intron hanging over the edge. */ if ((lf->tallStart < winStart) && (lf->tallStart > exon->start) && (lf->tallStart < exon->end)) linkedFeaturesMoveWinStart(lf->tallStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); else linkedFeaturesMoveWinStart(exon->start, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); } else if (bigExon) linkedFeaturesMoveWinEnd(exon->end, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); else linkedFeaturesMoveWinStart(exon->start, bufferToEdge, newWinSize, &newWinStart, &newWinEnd); if (!revStrand) safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", prevExonText, numExons-exonIx, numExons); else safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", nextExonText, exonIx+1, numExons); mapBoxJumpTo(hvg, x, y, w, h, tg, chromName, newWinStart, newWinEnd, mouseOverText); break; } } slFreeList(&exonList); } +void linkedFeaturesItemExonMaps(struct track *tg, struct hvGfx *hvg, void *item, double scale, + int y, int heightPer, int sItem, int eItem, + boolean lButton, boolean rButton, int buttonW) +/* Draw mapBoxes over exons and introns labeled with exon/intron numbers */ +{ +struct linkedFeatures *lf = item; +struct simpleFeature *exons = lf->components; +struct simpleFeature *exon = exons; +char *exonText, *intronText; +int numExons = 0; +int exonIx = 1; +struct slRef *exonList = NULL, *ref; +// TODO this exonText (and intronText) setting is just a made-up placeholder. +// could add a real setting name. Maybe someday extend to exon names (LRG?) instead of just exon numbers +if (startsWith("chain", tg->tdb->type) || startsWith("lrg", tg->tdb->track)) + { + exonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "exonText" , "Block"); + intronText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "intronText", "Gap" ); // what really goes here for chain type? + } +else + { + exonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "exonText" , "Exon" ); + intronText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "intronText", "Intron"); + } +while (exon != NULL) +/* Make a stupid list of exons separate from what's given. */ +/* It seems like lf->components isn't necessarily sorted. */ + { + refAdd(&exonList, exon); + exon = exon->next; + } +/* Now sort it. */ +slSort(&exonList, exonSlRefCmp); +numExons = slCount(exonList); +boolean revStrand = (lf->orientation == -1); +int eLast = -1; +int s = -1; +int e = -1; +char mouseOverText[256]; +boolean isExon = TRUE; +int picStart = insideX; +int picEnd = picStart + insideWidth; +if (lButton) + picStart += buttonW; +if (rButton) + picEnd -= buttonW; +for (ref = exonList; TRUE; ) + { + exon = ref->val; + if (isExon) + { + s = exon->start; + e = exon->end; + } + else + { + s = eLast; + e = exon->start; + } + // skip exons and introns that are completely outside the window + if (!(s > winEnd) || (e < winStart)) + { + int sClp = (s < winStart) ? winStart : s; + int eClp = (e > winEnd) ? winEnd : e; + + int sx = round((sClp - winStart)*scale) + insideX; + int ex = round((eClp - winStart)*scale) + insideX; + + // skip regions entirely outside available picture + // (accounts for space taken by exon arrows buttons) + if (!(sx > picEnd) || (ex < picStart)) + { + // clip it to avail pic + sx = (sx < picStart) ? picStart : sx; + ex = (ex > picEnd) ? picEnd : ex; + + int w = ex - sx; + + int exonIntronNumber; + char *exonIntronText; + int numExonIntrons = numExons; + if (isExon) + { + exonIntronText = exonText; + } + else + { + exonIntronText = intronText; + --numExonIntrons; // introns are one fewer than exons + } + + if (!revStrand) + exonIntronNumber = exonIx; + else + exonIntronNumber = numExonIntrons-exonIx+1; + + safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", exonIntronText, exonIntronNumber, numExonIntrons); + + if (w > 0) // draw exon or intron if width is greater than 0 + { + tg->mapItem(tg, hvg, item, mouseOverText, tg->mapItemName(tg, item), + sItem, eItem, sx, y, w, heightPer); + picStart = ex; // prevent pileups. is this right? add 1? does it work? + } + } + } + + if (isExon) + { + eLast = e; + ref = ref->next; + if (!ref) + break; + } + else + { + exonIx++; + } + isExon = !isExon; + + if (s > winEnd) // since the rest will also be outside the window + break; + + } +slFreeList(&exonList); +} + void linkedFeaturesLabelNextPrevItem(struct track *tg, boolean next) /* Default next-gene function for linkedFeatures. Changes winStart/winEnd * and updates position in cart. */ { int start = winStart; int end = winEnd; int size = winBaseCount; int sizeWanted = size; int bufferToEdge; struct bed *items = NULL; /* If there's stuff on the screen, skip past it. */ /* If not, skip to the edge of the window. */ if (next) { @@ -1987,43 +2199,46 @@ safef(pos, sizeof(pos), "%s:%d-%d", chromName, winStart+1, winEnd); cartSetString(cart, "position", cloneString(pos)); } } enum {blackShadeIx=9,whiteShadeIx=0}; char *getScoreFilterClause(struct cart *cart,struct trackDb *tdb,char *scoreColumn) // Returns "score >= ..." extra where clause if one is needed { if (scoreColumn == NULL) scoreColumn = "score"; struct dyString *extraWhere = newDyString(128); boolean and = FALSE; -extraWhere = dyAddFilterByClause(cart,tdb,extraWhere,NULL,&and); // gets trackDb 'filterBy' clause, which may filter by 'score', 'name', etc +// gets trackDb 'filterBy' clause, which may filter by 'score', 'name', etc +extraWhere = dyAddFilterByClause(cart,tdb,extraWhere,NULL,&and); extraWhere = dyAddAllScoreFilters(cart,tdb,extraWhere,&and); // All *Filter style filters -if (and == FALSE || strstrNoCase(extraWhere->string,"score in ") == NULL) // Cannot have both 'filterBy' score and 'scoreFilter' +if (and == FALSE // Cannot have both 'filterBy' score and 'scoreFilter' +|| strstrNoCase(extraWhere->string,"score in ") == NULL) extraWhere = dyAddFilterAsInt(cart,tdb,extraWhere,SCORE_FILTER,"0:1000",scoreColumn,&and); if (sameString(extraWhere->string, "")) return NULL; return dyStringCannibalize(&extraWhere); } void loadLinkedFeaturesWithLoaders(struct track *tg, struct slList *(*itemLoader)(char **row), struct linkedFeatures *(*lfFromWhatever)(struct slList *item), - char *scoreColumn, char *moreWhere, boolean (*itemFilter)(struct slList *item)) + char *scoreColumn, char *moreWhere, + boolean (*itemFilter)(struct slList *item)) /* Make a linkedFeatures loader by providing three functions: (1) a regular */ /* item loader found in all autoSql modules, (2) a custom myStruct->linkedFeatures */ /* translating function, and (3) a function to free the the thing loaded in (1). */ { struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; char **row; int rowOffset; struct linkedFeatures *lfList = NULL; char extraWhere[256] ; /* Use tg->tdb->track because subtracks inherit composite track's tdb * by default, and the variable is named after the composite track. */ if ((scoreColumn != NULL) && (cartVarExistsAnyLevel(cart, tg->tdb, FALSE, SCORE_FILTER))) { char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,scoreColumn); @@ -2340,33 +2555,32 @@ const struct linkedFeatures *b = *((struct linkedFeatures **)vb); int diff = a->filterColor - b->filterColor; if (diff == 0) diff = a->grayIx - b->grayIx; return diff; } int linkedFeaturesCmpStart(const void *va, const void *vb) /* Help sort linkedFeatures by starting pos. */ { const struct linkedFeatures *a = *((struct linkedFeatures **)va); const struct linkedFeatures *b = *((struct linkedFeatures **)vb); return a->start - b->start; } -void clippedBarbs(struct hvGfx *hvg, int x, int y, - int width, int barbHeight, int barbSpacing, int barbDir, Color color, - boolean needDrawMiddle) +void clippedBarbs(struct hvGfx *hvg, int x, int y, int width, + int barbHeight, int barbSpacing, int barbDir, Color color, boolean needDrawMiddle) /* Draw barbed line. Clip it to fit the window first though since * some barbed lines will span almost the whole chromosome, and the * clipping at the lower level is not efficient since we added * PostScript output support. */ { int x2 = x + width; if (barbDir == 0) return; x = max(x, hvg->clipMinX); x2 = min(x2, hvg->clipMaxX); width = x2 - x; if (width > 0) hvGfxBarbedHorizontalLine(hvg, x, y, width, barbHeight, barbSpacing, barbDir, @@ -2605,142 +2819,208 @@ color = saveColor; boolean baseColorNeedsCodons = (drawOpt == baseColorDrawItemCodons || drawOpt == baseColorDrawDiffCodons || drawOpt == baseColorDrawGenomicCodons); if (psl && baseColorNeedsCodons) { boolean isXeno = ((tg->subType == lfSubXeno) || (tg->subType == lfSubChain) || startsWith("mrnaBla", tg->table)); int sizeMul = pslIsProtein(psl) ? 3 : 1; lf->codons = baseColorCodonsFromPsl(lf, psl, sizeMul, isXeno, maxShade, drawOpt, tg); } else if (drawOpt > baseColorDrawOff) { struct genePred *gp = NULL; - if (startsWith("genePred", tg->tdb->type)) + if (startsWith("genePred", tg->tdb->type) || startsWith("bigGenePred", tg->tdb->type)) gp = (struct genePred *)(lf->original); if (gp && gp->cdsStart != gp->cdsEnd) lf->codons = baseColorCodonsFromGenePred(lf, gp, (drawOpt != baseColorDrawDiffCodons), cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, CODON_NUMBERING_SUFFIX, FALSE)); } if (psl && drawOpt == baseColorDrawCds && !zoomedToCdsColorLevel) baseColorSetCdsBounds(lf, psl, tg); tallStart = lf->tallStart; tallEnd = lf->tallEnd; -if ((tallStart == 0 && tallEnd == 0) && !sameWord(tg->table, "jaxQTL3")) +if ((tallStart == 0 && tallEnd == 0) && lf->start != 0 && !sameWord(tg->table, "jaxQTL3")) { // sometimes a bed <8 will get passed off as a bed 8, tsk tsk tallStart = lf->start; tallEnd = lf->end; } -x1 = round((double)((int)lf->start-winStart)*scale) + xOff; -x2 = round((double)((int)lf->end-winStart)*scale) + xOff; +int ourStart = lf->start; +if (ourStart < winStart) + ourStart = winStart; +int ourEnd = lf->end; +if (ourEnd > winEnd) + ourEnd = winEnd; +x1 = round((double)((int)ourStart-winStart)*scale) + xOff; +x2 = round((double)((int)ourEnd-winStart)*scale) + xOff; w = x2-x1; +if (lf->start==lf->end && w==0) // like a SNP insertion point of size=0 + { + w = 1; + hvGfxBox(hvg, x1, y, w, heightPer, color); + return; + } + +// are we highlighting this feature with background highlighting +if (lf->highlightColor && (lf->highlightMode == highlightBackground)) + { + // draw the background + hvGfxBox(hvg, x1, y, w, heightPer, lf->highlightColor); + + // draw the item slightly smaller + y++; + heightPer -=2; + } + if (!hideLine) { innerLine(hvg, x1, midY, w, color); } if (!hideArrows) { if ((intronGap == 0) && (vis == tvFull || vis == tvPack)) { + if (lf->highlightColor && (lf->highlightMode == highlightOutline)) + clippedBarbs(hvg, x1, midY, w, tl.barbHeight, tl.barbSpacing, + lf->orientation, lf->highlightColor, FALSE); + else clippedBarbs(hvg, x1, midY, w, tl.barbHeight, tl.barbSpacing, lf->orientation, bColor, FALSE); } } -components = (lf->codons && zoomedToCdsColorLevel) ? - lf->codons : lf->components; +components = (lf->codons && zoomedToCdsColorLevel) ? lf->codons : lf->components; for (sf = components; sf != NULL; sf = sf->next) { s = sf->start; e = sf->end; /* Draw UTR portion(s) of exon, if any: */ if (s < tallStart) { e2 = e; if (e2 > tallStart) e2 = tallStart; + if (lf->highlightColor && (lf->highlightMode == highlightOutline)) + { + drawScaledBoxSample(hvg, s, e2, scale, xOff, y+shortOff , shortHeight , + lf->highlightColor, lf->score); + drawScaledBoxSample(hvg, s, e2, scale, xOff + 1, y+shortOff + 1, shortHeight - 2, + color, lf->score); + } + else + { drawScaledBoxSample(hvg, s, e2, scale, xOff, y+shortOff, shortHeight, color, lf->score); + } s = e2; } if (e > tallEnd) { s2 = s; if (s2 < tallEnd) s2 = tallEnd; + if (lf->highlightColor && (lf->highlightMode == highlightOutline)) + { + drawScaledBoxSample(hvg, s2, e, scale, xOff, y+shortOff, shortHeight, + lf->highlightColor, lf->score); + drawScaledBoxSample(hvg, s2, e, scale, xOff+1, y+shortOff+1, shortHeight-2, + color, lf->score); + } + else + { drawScaledBoxSample(hvg, s2, e, scale, xOff, y+shortOff, shortHeight, color, lf->score); + } e = s2; } /* Draw "tall" portion of exon (or codon) */ if (e > s) { - if (drawOpt > baseColorDrawOff && - e + 6 >= winStart && s - 6 < winEnd && - (e-s <= 3 || !baseColorNeedsCodons)) - baseColorDrawItem(tg, lf, sf->grayIx, hvg, xOff, y, - scale, font, s, e, heightPer, - zoomedToCodonLevel, mrnaSeq, sf, psl, - drawOpt, - MAXPIXELS, winStart, color); + if (drawOpt > baseColorDrawOff + && e + 6 >= winStart + && s - 6 < winEnd + && (e-s <= 3 || !baseColorNeedsCodons)) + baseColorDrawItem(tg, lf, sf->grayIx, hvg, xOff, y, scale, font, s, e, heightPer, + zoomedToCodonLevel, mrnaSeq, sf, psl, drawOpt, MAXPIXELS, winStart, + color); + else + { + if (lf->highlightColor && (lf->highlightMode == highlightOutline)) + { + drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer, + lf->highlightColor, lf->score ); + drawScaledBoxSample(hvg, s, e, scale, xOff+1, y+1, heightPer-2, + color, lf->score ); + } else { + if (tg->drawLabelInBox) + { + drawScaledBoxSampleLabel(hvg, s, e, scale, xOff, y, heightPer, + color, font, lf->name ); + // exon arrows would overlap the text + exonArrowsAlways = FALSE; + exonArrows = FALSE; + } + + else drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer, color, lf->score); + } - if (exonArrowsAlways || (exonArrows && /* Display barbs only if no intron is visible on the item. This occurs when the exon completely spans the window, or when it is the first or last intron in the feature and the following/preceding intron isn't visible */ - (sf->start <= winStart || sf->start == lf->start) && - (sf->end >= winEnd || sf->end == lf->end))) + if (exonArrowsAlways + || ( exonArrows + && (sf->start <= winStart || sf->start == lf->start) + && (sf->end >= winEnd || sf->end == lf->end))) { Color barbColor = hvGfxContrastingColor(hvg, color); x1 = round((double)((int)s-winStart)*scale) + xOff; x2 = round((double)((int)e-winStart)*scale) + xOff; w = x2-x1; - clippedBarbs(hvg, x1+1, midY, x2-x1-2, - tl.barbHeight, tl.barbSpacing, lf->orientation, - barbColor, TRUE); + clippedBarbs(hvg, x1+1, midY, x2-x1-2, tl.barbHeight, tl.barbSpacing, + lf->orientation, barbColor, TRUE); } } } } if ((intronGap > 0) || chainLines) lfDrawSpecialGaps(lf, intronGap, chainLines, gapFactor, tg, hvg, xOff, y, scale, color, bColor, vis); if (vis != tvDense) { /* If highlighting differences between aligned sequence and genome when * zoomed way out, this must be done in a separate pass after exons are * drawn so that exons sharing the pixel don't overdraw differences. */ if (indelShowQueryInsert || indelShowPolyA) baseColorOverdrawQInsert(tg, lf, hvg, xOff, y, scale, heightPer, mrnaSeq, psl, winStart, drawOpt, indelShowQueryInsert, indelShowPolyA); baseColorOverdrawDiff(tg, lf, hvg, xOff, y, scale, heightPer, mrnaSeq, psl, winStart, drawOpt); baseColorDrawCleanup(lf, &mrnaSeq, &psl); } } static void lfSeriesDrawConnecter(struct linkedFeaturesSeries *lfs, - struct hvGfx *hvg, int start, int end, double scale, int xOff, int midY, - Color color, Color bColor, enum trackVisibility vis) + struct hvGfx *hvg, int start, int end, double scale, int xOff, + int midY, Color color, Color bColor, enum trackVisibility vis) /* Draw connection between two sets of linked features. */ { if (start != -1 && !lfs->noLine) { int x1 = round((double)((int)start-winStart)*scale) + xOff; int x2 = round((double)((int)end-winStart)*scale) + xOff; int w = x2-x1; if (w > 0) { if (vis == tvFull || vis == tvPack) clippedBarbs(hvg, x1, midY, w, tl.barbHeight, tl.barbSpacing, lfs->orientation, bColor, TRUE); hvGfxLine(hvg, x1, midY, x2, midY, color); } } @@ -2826,159 +3106,184 @@ return highlight; } double scaleForWindow(double width, int seqStart, int seqEnd) /* Return the scale for the window. */ { return width / (seqEnd - seqStart); } boolean nextItemCompatible(struct track *tg) /* Check to see if we draw nextPrev item buttons on a track. */ { return (withNextExonArrows && tg->nextExonButtonable && tg->nextPrevExon); } +boolean exonNumberMapsCompatible(struct track *tg, enum trackVisibility vis) +/* Check to see if we draw exon and intron maps labeling their number. */ +{ +boolean exonNumbers = sameString(trackDbSettingOrDefault(tg->tdb, "exonNumbers", "on"), "on"); +return (withExonNumbers && exonNumbers && (vis==tvFull || vis==tvPack) && (winEnd - winStart < 400000) + && (tg->nextPrevExon==linkedFeaturesNextPrevItem)); +} + void genericMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) /* This is meant to be used by genericDrawItems to set to tg->mapItem in */ /* case tg->mapItem isn't set to anything already. */ { // Don't bother if we are imageV2 and a dense child. if (!theImgBox || tg->limitedVis != tvDense || !tdbIsCompositeChild(tg->tdb)) { char *directUrl = trackDbSetting(tg->tdb, "directUrl"); boolean withHgsid = (trackDbSetting(tg->tdb, "hgsid") != NULL); mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, tg->track, mapItemName, itemName, directUrl, withHgsid, NULL); } } -void genericDrawNextItemStuff(struct track *tg, struct hvGfx *hvg, enum trackVisibility vis, struct slList *item, - int x2, int textX, int y, int heightPer, - boolean snapLeft, Color color) +void genericDrawNextItemStuff(struct track *tg, struct hvGfx *hvg, enum trackVisibility vis, + struct slList *item, double scale, int x2, int x1, int textX, int y, int heightPer, + Color color, boolean doButtons) /* After the item is drawn in genericDrawItems, draw next/prev item related */ /* buttons and the corresponding mapboxes. */ { int buttonW = heightPer-1 + 2*NEXT_ITEM_ARROW_BUFFER; int s = tg->itemStart(tg, item); int e = tg->itemEnd(tg, item); boolean rButton = FALSE; boolean lButton = FALSE; /* Draw the actual triangles. These are always at the edge of the window. */ -if (s < winStart) +if (doButtons && (s < winStart)) { lButton = TRUE; hvGfxNextItemButton(hvg, insideX + NEXT_ITEM_ARROW_BUFFER, y, heightPer-1, heightPer-1, color, MG_WHITE, FALSE); } -if (e > winEnd) +if (doButtons && (e > winEnd)) { rButton = TRUE; hvGfxNextItemButton(hvg, insideX + insideWidth - NEXT_ITEM_ARROW_BUFFER - heightPer, y, heightPer-1, heightPer-1, color, MG_WHITE, TRUE); } -/* If we're in pack, there's some crazy logic. */ + +if ((vis == tvFull) || (vis == tvPack)) + { + /* Make the button mapboxes. */ + if (lButton) + tg->nextPrevExon(tg, hvg, item, insideX, y, buttonW, heightPer, FALSE); + if (rButton) + tg->nextPrevExon(tg, hvg, item, insideX + insideWidth - buttonW, y, buttonW, heightPer, TRUE); + } + +boolean compat = exonNumberMapsCompatible(tg, vis); if (vis == tvPack) { int w = x2-textX; if (lButton) - { + { // if left-button, the label will be on far left, split out a map just for that label. tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), s, e, textX, y, insideX-textX, heightPer); - tg->nextPrevExon(tg, hvg, item, insideX, y, buttonW, heightPer, FALSE); + textX = insideX + buttonW; // continue on the right side of the left exon button + w = x2-textX; + } if (rButton) { - tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), - s, e, insideX + buttonW, y, x2 - (insideX + 2*buttonW), heightPer); - tg->nextPrevExon(tg, hvg, item, x2-buttonW, y, buttonW, heightPer, TRUE); - } - else - tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), - s, e, insideX + buttonW, y, x2 - (insideX + buttonW), heightPer); + w -= buttonW; } - else if (snapLeft && rButton) - /* This is a special case where there's a next-item button, NO */ - /* prev-item button, AND the gene name is drawn left of the browser window. */ - { - tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), - s, e, textX, y, x2 - buttonW - textX, heightPer); - tg->nextPrevExon(tg, hvg, item, x2-buttonW, y, buttonW, heightPer, TRUE); + + if (compat) + { // draw labeled exon/intron maps with exon/intron numbers + linkedFeaturesItemExonMaps(tg, hvg, item, scale, y, heightPer, s, e, lButton, rButton, buttonW); + x2 = x1; + w = x2-textX; } - else if (rButton) + // if not already mapped, pick up the label + if (!(lButton && compat)) { tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), - s, e, textX, y, w - buttonW, heightPer); - tg->nextPrevExon(tg, hvg, item, x2-buttonW, y, buttonW, heightPer, TRUE); - } - else - tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), s, e, textX, y, w, heightPer); } -/* Full mode is a little easier to deal with. */ + } + else if (vis == tvFull) { int geneMapBoxX = insideX; int geneMapBoxW = insideWidth; - /* Draw the first gene mapbox, in the left margin. */ + /* Draw the first gene label mapbox, in the left margin. */ #ifndef IMAGEv2_NO_LEFTLABEL_ON_FULL int trackPastTabX = (withLeftLabels ? trackTabWidth : 0); #ifdef IMAGEv2_SHORT_MAPITEMS char *name = tg->itemName(tg, item); if (*name != '\0') tg->mapItem(tg, hvg, item, name, tg->mapItemName(tg, item), s, e, trackPastTabX, y, insideX - trackPastTabX, heightPer); #else///ndef IMAGEv2_SHORT_MAPITEMS tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), s, e, trackPastTabX, y, insideX - trackPastTabX, heightPer); #endif///ndef IMAGEv2_SHORT_MAPITEMS #endif///ndef IMAGEv2_NO_LEFTLABEL_ON_FULL - /* Make the button mapboxes. */ - if (lButton) - tg->nextPrevExon(tg, hvg, item, insideX, y, buttonW, heightPer, FALSE); - if (rButton) - tg->nextPrevExon(tg, hvg, item, insideX + insideWidth - buttonW, y, buttonW, heightPer, TRUE); /* Depending on which button mapboxes we drew, draw the remaining mapbox. */ - if (lButton && rButton) + if (lButton) { geneMapBoxX += buttonW; - geneMapBoxW -= 2 * buttonW; + geneMapBoxW -= buttonW; } - else if (lButton) + if (rButton) { - geneMapBoxX += buttonW; geneMapBoxW -= buttonW; } - else if (rButton) - geneMapBoxW -= buttonW; #ifdef IMAGEv2_SHORT_MAPITEMS if (x2 > 0) { geneMapBoxX = textX; geneMapBoxW = x2-geneMapBoxX; if (geneMapBoxW < 5) // Full with short labels but don't make tiny map items { geneMapBoxX -= (5 - geneMapBoxW)/2; geneMapBoxW = 5; } } #endif//def IMAGEv2_SHORT_MAPITEMS + if (compat) + { // draw labeled exon/intron maps with exon/intron numbers + linkedFeaturesItemExonMaps(tg, hvg, item, scale, y, heightPer, s, e, lButton, rButton, buttonW); + if (!lButton) + { + int w = x1 - geneMapBoxX; + if (w > 0) + tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), + s, e, geneMapBoxX, y, w, heightPer); + } + if (!rButton) + { + int w = geneMapBoxX + geneMapBoxW - x2; + if (w > 0) + tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), + s, e, x2, y, w, heightPer); + } + } + else + { tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), s, e, geneMapBoxX, y, geneMapBoxW, heightPer); } } +} + + static void genericDrawOverflowItem(struct track *tg, struct spaceNode *sn, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, double scale, int overflowRow, boolean firstOverflow) /* genericDrawItems logic for drawing an overflow row */ { /* change some state to paint it in the "overflow" row. */ enum trackVisibility origVis = tg->limitedVis; int origLineHeight = tg->lineHeight; int origHeightPer = tg->heightPer; tg->limitedVis = tvDense; tg->heightPer = tl.fontHeight; tg->lineHeight = tl.fontHeight+1; struct slList *item = sn->val; @@ -3009,53 +3314,56 @@ hvGfxSetClip(hvgSide, insideX, yOff, insideWidth, tg->height); } /* restore state */ tg->limitedVis = origVis; tg->heightPer = origHeightPer; tg->lineHeight = origLineHeight; } static void genericDrawItem(struct track *tg, struct spaceNode *sn, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, Color labelColor, enum trackVisibility vis, double scale, boolean withLeftLabels) /* draw one non-overflow item */ { struct slList *item = sn->val; -boolean withLabels = (withLeftLabels && (vis == tvPack) && !tg->drawName); int s = tg->itemStart(tg, item); int e = tg->itemEnd(tg, item); int sClp = (s < winStart) ? winStart : s; int eClp = (e > winEnd) ? winEnd : e; int x1 = round((sClp - winStart)*scale) + xOff; int x2 = round((eClp - winStart)*scale) + xOff; int textX = x1; -char *name = tg->itemName(tg, item); + +if (tg->drawLabelInBox) + withLeftLabels = FALSE; if (tg->itemNameColor != NULL) { color = tg->itemNameColor(tg, item, hvg); labelColor = color; if (withLeftLabels && isTooLightForTextOnWhite(hvg, color)) labelColor = somewhatDarkerColor(hvg, color); } int y = yOff + tg->lineHeight * sn->row; tg->drawItemAt(tg, item, hvg, xOff, y, scale, font, color, vis); -/* pgSnp tracks may change flags between items */ -withLabels = (withLeftLabels && withIndividualLabels && (vis == tvPack) && !tg->drawName); + +/* pgSnpDrawAt may change withIndividualLabels between items */ +boolean withLabels = (withLeftLabels && withIndividualLabels && (vis == tvPack) && !tg->drawName); if (withLabels) { + char *name = tg->itemName(tg, item); int nameWidth = mgFontStringWidth(font, name); int dotWidth = tl.nWidth/2; boolean snapLeft = FALSE; boolean drawNameInverted = highlightItem(tg, item); textX -= nameWidth + dotWidth; snapLeft = (textX < insideX); /* Special tweak for expRatio in pack mode: force all labels * left to prevent only a subset from being placed right: */ snapLeft |= (startsWith("expRatio", tg->tdb->type)); #ifdef IMAGEv2_NO_LEFTLABEL_ON_FULL if (theImgBox == NULL && snapLeft) #else///ifndef IMAGEv2_NO_LEFTLABEL_ON_FULL if (snapLeft) /* Snap label to the left. */ #endif ///ndef IMAGEv2_NO_LEFTLABEL_ON_FULL { @@ -3082,169 +3390,348 @@ { hvGfxBox(hvg, textX - 1, y, nameWidth+1, tg->heightPer-1, color); hvGfxTextRight(hvg, textX, y, nameWidth, tg->heightPer, MG_WHITE, font, name); } else hvGfxTextRight(hvg, textX, y, nameWidth, tg->heightPer, labelColor, font, name); } } if (!tg->mapsSelf) { int w = x2-textX; /* Arrows? */ if (w > 0) { if (nextItemCompatible(tg)) - genericDrawNextItemStuff(tg, hvg, vis, item, x2, textX, y, tg->heightPer, FALSE, - color); + genericDrawNextItemStuff(tg, hvg, vis, item, scale, x2, x1, textX, y, tg->heightPer, color, TRUE); + else if (exonNumberMapsCompatible(tg, vis)) + genericDrawNextItemStuff(tg, hvg, vis, item, scale, x2, x1, textX, y, tg->heightPer, color, FALSE); else { tg->mapItem(tg, hvg, item, tg->itemName(tg, item), tg->mapItemName(tg, item), s, e, textX, y, w, tg->heightPer); } } } withIndividualLabels = TRUE; /* reset in case done with pgSnp */ } -static void genericDrawItemsPackSquish(struct track *tg, - int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, - MgFont *font, Color color, enum trackVisibility vis) -/* genericDrawItems logic for pack and squish modes */ +static int normalizeCount(struct preDrawElement *el, double countFactor, + double minVal, double maxVal, double sumData, double sumSquares) +/* Normalize statistics to be based on an integer number of valid bases. + * Integer value is the smallest integer not less than countFactor. */ { -double scale = scaleForWindow(width, seqStart, seqEnd); -int lineHeight = tg->lineHeight; -struct spaceNode *sn; -int maxHeight = maximumTrackHeight(tg); -int overflowRow = (maxHeight - tl.fontHeight +1) / lineHeight; -boolean firstOverflow = TRUE; +bits32 validCount = ceil(countFactor); +double normFactor = (double)validCount/countFactor; -hvGfxSetClip(hvg, insideX, yOff, insideWidth, tg->height); -assert(tg->ss); +el->count = validCount; +el->min = minVal; +el->max = maxVal; +el->sumData = sumData * normFactor; +el->sumSquares = sumSquares * normFactor; -/* Loop through and draw each item individually */ -for (sn = tg->ss->nodeList; sn != NULL; sn = sn->next) +return validCount; +} + +static unsigned *countOverlaps(struct track *track) +/* Count up overlap of linked features. */ { - if (sn->row >= overflowRow) +struct slList *items = track->items; +struct slList *item; +unsigned size = winEnd - winStart; +unsigned *counts = needHugeZeroedMem(size * sizeof(unsigned)); + +for (item = items; item; item = item->next) { - genericDrawOverflowItem(tg, sn, hvg, xOff, yOff, width, font, color, - scale, overflowRow, firstOverflow); - firstOverflow = FALSE; - } - else - genericDrawItem(tg, sn, hvg, xOff, yOff, width, font, color, color, vis, - scale, withLeftLabels); + unsigned start = track->itemStart(track, item); + unsigned end = track->itemEnd(track, item); + if (positiveRangeIntersection(start, end, winStart, winEnd) <= 0) + continue; + + int x1 = max((int)start - (int)winStart, 0); + int x2 = min((int)end - (int)winStart, size); + + for(; x1 < x2; x1++) + counts[x1]++; } -hvGfxUnclip(hvg); +return counts; } -static void genericDrawItemsFullDense(struct track *tg, - int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, - MgFont *font, Color color, enum trackVisibility vis) -/* genericDrawItems logic for full and dense modes */ +static void countsToPixelsUp(unsigned *counts, struct preDrawContainer *pre) +/* Up sample counts into pixels. */ { -double scale = scaleForWindow(width, seqStart, seqEnd); -struct slList *item; -int y = yOff; -for (item = tg->items; item != NULL; item = item->next) +int preDrawZero = pre->preDrawZero; +unsigned size = winEnd - winStart; +double countsPerPixel = size / (double) insideWidth; +int pixel; + +for (pixel=0; pixel<insideWidth; ++pixel) { - if(tg->itemColor != NULL) - color = tg->itemColor(tg, item, hvg); - tg->drawItemAt(tg, item, hvg, xOff, y, scale, font, color, vis); - if (vis == tvFull) + struct preDrawElement *pe = &pre->preDraw[pixel + preDrawZero]; + unsigned index = pixel * countsPerPixel; + pe->count = 1; + pe->min = counts[index]; + pe->max = counts[index]; + pe->sumData = counts[index] ; + pe->sumSquares = counts[index] * counts[index]; + } +} + +static void countsToPixelsDown(unsigned *counts, struct preDrawContainer *pre) +/* Down sample counts into pixels. */ { - /* The doMapItems will make the mapboxes normally but make */ - /* them here if we're drawing nextItem buttons. */ - if (nextItemCompatible(tg)) +int preDrawZero = pre->preDrawZero; +unsigned size = winEnd - winStart; +double countsPerPixel = size / (double) insideWidth; +int pixel; + +for (pixel=0; pixel<insideWidth; ++pixel) + { + struct preDrawElement *pe = &pre->preDraw[pixel + preDrawZero]; + double startReal = pixel * countsPerPixel; + double endReal = (pixel + 1) * countsPerPixel; + unsigned startUns = startReal; + unsigned endUns = endReal; + double realCount, realSum, realSumSquares, max, min; + + realCount = realSum = realSumSquares = 0.0; + max = min = counts[startUns]; + + assert(startUns != endUns); + unsigned ceilUns = ceil(startReal); + + if (ceilUns != startUns) + { + /* need a fraction of the first count */ + double frac = (double)ceilUns - startReal; + realCount = frac; + realSum = frac * counts[startUns]; + realSumSquares = realSum * realSum; + startUns++; + } + + // add in all the counts that are totally in this pixel + for(; startUns < endUns; startUns++) + { + realCount += 1.0; + realSum += counts[startUns]; + realSumSquares += counts[startUns] * counts[startUns]; + if (max < counts[startUns]) + max = counts[startUns]; + if (min > counts[startUns]) + min = counts[startUns]; + } + + // add any fraction of the count that's only partially in this pixel + double lastFrac = endReal - endUns; + double lastSum = lastFrac * counts[endUns]; + if (lastFrac > 0.0) + { + if (max < counts[endUns]) + max = counts[endUns]; + if (min > counts[endUns]) + min = counts[endUns]; + realCount += lastFrac; + realSum += lastSum; + realSumSquares += lastSum * lastSum; + } + + pe->count = normalizeCount(pe, realCount, min, max, realSum, realSumSquares); + } +} + +static void countsToPixels(unsigned *counts, struct preDrawContainer *pre) +/* Sample counts into pixels. */ +{ +unsigned size = winEnd - winStart; +double countsPerPixel = size / (double) insideWidth; + +if (countsPerPixel <= 1.0) + countsToPixelsUp(counts, pre); +else + countsToPixelsDown(counts, pre); +} + +static void genericDrawItemsWiggle(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* Draw a list of linked features into a wiggle. */ +{ +struct preDrawContainer *pre = tg->preDrawContainer = initPreDrawContainer(insideWidth); +unsigned *counts = countOverlaps(tg); + +countsToPixels(counts, pre); +freez(&counts); + +hvGfxSetClip(hvg, insideX, yOff, insideWidth, tg->height); +tg->mapsSelf = FALSE; // some magic to turn off the link out +wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis, + tg->preDrawContainer, tg->preDrawContainer->preDrawZero, tg->preDrawContainer->preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit); +tg->mapsSelf = TRUE; +hvGfxUnclip(hvg); +} + +static void genericDrawItemsPackSquish(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* genericDrawItems logic for pack and squish modes */ +{ +double scale = scaleForWindow(width, seqStart, seqEnd); +int lineHeight = tg->lineHeight; +struct spaceNode *sn; +int maxHeight = maximumTrackHeight(tg); +int overflowRow = (maxHeight - tl.fontHeight +1) / lineHeight; +boolean firstOverflow = TRUE; + +hvGfxSetClip(hvg, insideX, yOff, insideWidth, tg->height); +assert(tg->ss); + +/* Loop through and draw each item individually */ +for (sn = tg->ss->nodeList; sn != NULL; sn = sn->next) + { + if (sn->row >= overflowRow) + { + genericDrawOverflowItem(tg, sn, hvg, xOff, yOff, width, font, color, + scale, overflowRow, firstOverflow); + firstOverflow = FALSE; + } + else + genericDrawItem(tg, sn, hvg, xOff, yOff, width, font, color, color, vis, + scale, withLeftLabels); + } + +hvGfxUnclip(hvg); +} + +static void genericDrawItemsFullDense(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* genericDrawItems logic for full and dense modes */ +{ +double scale = scaleForWindow(width, seqStart, seqEnd); +struct slList *item; +int y = yOff; +for (item = tg->items; item != NULL; item = item->next) + { + if (tg->itemColor != NULL) + color = tg->itemColor(tg, item, hvg); + tg->drawItemAt(tg, item, hvg, xOff, y, scale, font, color, vis); + if (vis == tvFull) + { + /* The doMapItems will make the mapboxes normally but make */ + /* them here if we're drawing nextItem buttons. */ + if (nextItemCompatible(tg)) #ifdef IMAGEv2_SHORT_MAPITEMS { // Convert start/end coordinates to pix int s = tg->itemStart(tg, item); int e = tg->itemEnd(tg, item); int sClp = (s < winStart) ? winStart : s; int eClp = (e > winEnd) ? winEnd : e; int x1 = round((sClp - winStart)*scale) + xOff; int x2 = round((eClp - winStart)*scale) + xOff; #ifdef IMAGEv2_NO_LEFTLABEL_ON_FULL if (theImgBox != NULL && vis == tvFull) // dragScroll >1x has no bed full leftlabels, { // but in image labels like pack. char *name = tg->itemName(tg, item); int nameWidth = mgFontStringWidth(font, name); int textX = round((s - winStart)*scale) + xOff; textX -= (nameWidth + 2); if (textX >= insideX && nameWidth > 0) { x1 = textX; // extends the map item to cover this label Color itemNameColor = tg->itemNameColor(tg, item, hvg); hvGfxTextRight(hvg,textX,y,nameWidth,tg->heightPer,itemNameColor,font,name); } } #endif ///def IMAGEv2_NO_LEFTLABEL_ON_FULL - genericDrawNextItemStuff(tg, hvg, vis, item, x2, x1, y, tg->heightPer, FALSE,color); + genericDrawNextItemStuff(tg, hvg, vis, item, scale, x2, x1, x1, y, tg->heightPer, color); } #else//ifndef IMAGEv2_SHORT_MAPITEMS - genericDrawNextItemStuff(tg, hvg, vis, item, -1, -1, y, tg->heightPer, FALSE, - color); + { + // Convert start/end coordinates to pix + int s = tg->itemStart(tg, item); + int e = tg->itemEnd(tg, item); + int sClp = (s < winStart) ? winStart : s; + int eClp = (e > winEnd) ? winEnd : e; + int x1 = round((sClp - winStart)*scale) + xOff; + int x2 = round((eClp - winStart)*scale) + xOff; + genericDrawNextItemStuff(tg, hvg, vis, item, scale, x2, x1, -1, y, tg->heightPer, color, TRUE); // was -1, -1, -1 + } + else if (exonNumberMapsCompatible(tg, vis)) + { + // Convert start/end coordinates to pix + int s = tg->itemStart(tg, item); + int e = tg->itemEnd(tg, item); + int sClp = (s < winStart) ? winStart : s; + int eClp = (e > winEnd) ? winEnd : e; + int x1 = round((sClp - winStart)*scale) + xOff; + int x2 = round((eClp - winStart)*scale) + xOff; + genericDrawNextItemStuff(tg, hvg, vis, item, scale, x2, x1, -1, y, tg->heightPer, color, FALSE); // was -1, -1, -1 + } #endif//ndef IMAGEv2_SHORT_MAPITEMS y += tg->lineHeight; } } } -void genericDrawItems(struct track *tg, - int seqStart, int seqEnd, +void genericDrawItems(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw generic item list. Features must be fixed height * and tg->drawItemAt has to be filled in. */ { if (tg->mapItem == NULL) tg->mapItem = genericMapItem; -if (vis != tvDense && (! bedItemRgb(tg->tdb)) && baseColorCanDraw(tg)) +if (vis != tvDense && baseColorCanDraw(tg)) baseColorInitTrack(hvg, tg); -if (vis == tvPack || vis == tvSquish) +boolean doWiggle = cartOrTdbBoolean(cart, tg->tdb, "doWiggle" , FALSE); +if (doWiggle) + { + genericDrawItemsWiggle(tg, seqStart, seqEnd, hvg, xOff, yOff, width, + font, color, vis); + } +else if (vis == tvPack || vis == tvSquish) { genericDrawItemsPackSquish(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } else genericDrawItemsFullDense(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } -void linkedFeaturesSeriesDraw(struct track *tg, - int seqStart, int seqEnd, +void linkedFeaturesSeriesDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw linked features items. */ { clearColorBin(); if (vis == tvDense && tg->colorShades) slSort(&tg->items, cmpLfsWhiteToBlack); genericDrawItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } void linkedFeaturesDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw linked features items. */ { clearColorBin(); + if (tg->items == NULL && vis == tvDense && canDrawBigBedDense(tg)) { bigBedDrawDense(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color); } else { if (vis == tvDense && tg->colorShades) slSort(&tg->items, cmpLfWhiteToBlack); genericDrawItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } } void incRange(UBYTE *start, int size) /* Add one to range of bytes, taking care to not overflow. */ @@ -3291,31 +3778,31 @@ int w = x2-x1; if (w >= 0) { if (w == 0) w = 1; incRange(useCounts+x1, w); } } static void countLinkedFeaturesBaseUse(struct linkedFeatures *lf, int width, int baseWidth, UBYTE *useCounts, UBYTE *gapUseCounts, bool rc) /* increment base use counts for a set of linked features */ { /* Performence-sensitive code. Most of the overhead is in the mapping of base * to pixel. This was change from using roundingScale() to doing it all in - * floating point, with the divide take out of the loop. To avoid adding more + * floating point, with the divide taken out of the loop. To avoid adding more * overhead when rendering gaps, the translation to pixel coordinates is done * here, and then we save the previous block coordinates for use in marking * the gap. */ struct simpleFeature *sf; double scale = ((double)width)/((double)baseWidth); int x1 = -1, x2 = -1, prevX1 = -1, prevX2 = -1; /* pixel coords */ for (sf = lf->components; sf != NULL; sf = sf->next) { x1 = round(((double)(sf->start-winStart)) * scale); x2 = round(((double)(sf->end-winStart)) * scale); /* need to adjust x1/x2 before saving as prevX1/prevX2 */ if (x1 < 0) x1 = 0; if (x2 >= width) x2 = width-1; @@ -3380,32 +3867,31 @@ Color *colors = needMem(sizeof(Color) * width); grayThreshold(useCounts, width, colors); hvGfxVerticalSmear(hvg,xOff,yOff,width,lineHeight,colors,TRUE); freeMem(useCounts); if (gapUseCounts != NULL) { int midY = yOff + (tg->heightPer>>1); grayThreshold(gapUseCounts, width, colors); hvGfxVerticalSmear(hvg,xOff,midY,width,1,colors,TRUE); freeMem(gapUseCounts); } } -void linkedFeaturesAverageDense(struct track *tg, - int seqStart, int seqEnd, +void linkedFeaturesAverageDense(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw dense linked features items. */ { if (vis == tvDense) linkedFeaturesDrawAverage(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); else linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } int lfCalcGrayIx(struct linkedFeatures *lf) /* Calculate gray level from components. */ { struct simpleFeature *sf; int count = 0; @@ -3447,77 +3933,105 @@ int linkedFeaturesItemStart(struct track *tg, void *item) /* Return start chromosome coordinate of item. */ { struct linkedFeatures *lf = item; return lf->start; } int linkedFeaturesItemEnd(struct track *tg, void *item) /* Return end chromosome coordinate of item. */ { struct linkedFeatures *lf = item; return lf->end; } + +static void linkedFeaturesMapItem(struct track *tg, struct hvGfx *hvg, void *item, + char *itemName, char *mapItemName, int start, int end, + int x, int y, int width, int height) +/* Draw the mouseOver (aka statusLine) text from the mouseOver field of lf + * Fallback to itemName if there is no mouseOver field. + * (derived from genericMapItem) */ +{ +// Don't bother if we are imageV2 and a dense child. +if (theImgBox && tg->limitedVis == tvDense && tdbIsCompositeChild(tg->tdb)) + return; + +struct linkedFeatures *lf = item; +char *newItemName = (isEmpty(lf->mouseOver)) ? itemName: lf->mouseOver; + +// copied from genericMapItem +char *directUrl = trackDbSetting(tg->tdb, "directUrl"); +boolean withHgsid = (trackDbSetting(tg->tdb, "hgsid") != NULL); +mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, tg->track, + mapItemName, newItemName, directUrl, withHgsid, NULL); +} + void linkedFeaturesMethods(struct track *tg) /* Fill in track methods for linked features. */ { tg->freeItems = linkedFeaturesFreeItems; tg->drawItems = linkedFeaturesDraw; tg->drawItemAt = linkedFeaturesDrawAt; tg->itemName = linkedFeaturesName; tg->mapItemName = linkedFeaturesName; +tg->mapItem = linkedFeaturesMapItem; tg->totalHeight = tgFixedTotalHeightNoOverflow; tg->itemHeight = tgFixedItemHeight; tg->itemStart = linkedFeaturesItemStart; tg->itemEnd = linkedFeaturesItemEnd; tg->itemNameColor = linkedFeaturesNameColor; tg->nextPrevExon = linkedFeaturesNextPrevItem; tg->nextPrevItem = linkedFeaturesLabelNextPrevItem; + +if (trackDbSettingClosestToHomeOn(tg->tdb, "linkIdInName")) + { + tg->mapItemName = linkedFeaturesNameField1; + tg->itemName = linkedFeaturesNameNotField1; + } } int linkedFeaturesSeriesItemStart(struct track *tg, void *item) /* Return start chromosome coordinate of item. */ { struct linkedFeaturesSeries *lfs = item; return lfs->start; } int linkedFeaturesSeriesItemEnd(struct track *tg, void *item) /* Return end chromosome coordinate of item. */ { struct linkedFeaturesSeries *lfs = item; return lfs->end; } void linkedFeaturesSeriesMethods(struct track *tg) /* Fill in track methods for linked features.series */ { tg->freeItems = freeLinkedFeaturesSeriesItems; tg->drawItems = linkedFeaturesSeriesDraw; tg->drawItemAt = linkedFeaturesSeriesDrawAt; tg->itemName = linkedFeaturesSeriesName; tg->mapItemName = linkedFeaturesSeriesName; tg->totalHeight = tgFixedTotalHeightNoOverflow; tg->itemHeight = tgFixedItemHeight; tg->itemStart = linkedFeaturesSeriesItemStart; tg->itemEnd = linkedFeaturesSeriesItemEnd; } -struct linkedFeatures *lfFromBedExtra(struct bed *bed, int scoreMin, - int scoreMax) +struct linkedFeatures *lfFromBedExtra(struct bed *bed, int scoreMin, int scoreMax) /* Return a linked feature from a (full) bed. */ { struct linkedFeatures *lf; struct simpleFeature *sf, *sfList = NULL; int grayIx = grayInRange(bed->score, scoreMin, scoreMax); int *starts = bed->chromStarts, start; int *sizes = bed->blockSizes; int blockCount = bed->blockCount, i; assert(starts != NULL && sizes != NULL && blockCount > 0); AllocVar(lf); lf->grayIx = grayIx; lf->name = cloneString(bed->name); lf->orientation = orientFromChar(bed->strand[0]); @@ -3585,110 +4099,122 @@ lf->extra = (void *)USE_ITEM_RGB; lf->filterColor = (unsigned)bed->expIds[i]; slAddHead(&lfList, lf); } slReverse(&lfList); lfs->features = lfList; lfs->noLine = FALSE; return lfs; } struct linkedFeatures *lfFromBed(struct bed *bed) { return lfFromBedExtra(bed, 0, 1000); } -struct linkedFeaturesSeries *lfsFromBed(struct lfs *lfsbed) +struct linkedFeaturesSeries *lfsFromBed(struct lfs *lfsbed, char *tdbPslTable) /* Create linked feature series object from database bed record */ { struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; -char **row, rest[32]; +char **row, rest[64]; int rowOffset, i; struct linkedFeaturesSeries *lfs; struct linkedFeatures *lfList = NULL, *lf; AllocVar(lfs); lfs->name = cloneString(lfsbed->name); lfs->start = lfsbed->chromStart; lfs->end = lfsbed->chromEnd; lfs->orientation = orientFromChar(lfsbed->strand[0]); /* Get linked features */ for (i = 0; i < lfsbed->lfCount; i++) { AllocVar(lf); - sprintf(rest, "qName = '%s'", lfsbed->lfNames[i]); - sr = hRangeQuery(conn, lfsbed->pslTable, lfsbed->chrom, - lfsbed->lfStarts[i], lfsbed->lfStarts[i] + lfsbed->lfSizes[i], rest, &rowOffset); + sqlSafefFrag(rest, sizeof rest, "qName = '%s'", lfsbed->lfNames[i]); + + // use psl table from trackDb, if specified there + char *pslTable = lfsbed->pslTable; + if (tdbPslTable != NULL) + pslTable = tdbPslTable; + + sr = hRangeQuery(conn, pslTable, lfsbed->chrom, lfsbed->lfStarts[i], + lfsbed->lfStarts[i] + lfsbed->lfSizes[i], rest, &rowOffset); if ((row = sqlNextRow(sr)) != NULL) { struct psl *psl = pslLoad(row+rowOffset); lf = lfFromPsl(psl, FALSE); slAddHead(&lfList, lf); } sqlFreeResult(&sr); } slReverse(&lfList); sqlFreeResult(&sr); hFreeConn(&conn); lfs->features = lfList; return lfs; } -static struct linkedFeaturesSeries *lfsFromBedsInRange(char *table, int start, int end, char *chromName) +static struct linkedFeaturesSeries *lfsFromBedsInRange(struct track *tg, int start, int end, + char *chromName) /* Return linked features from range of table. */ { +char *table = tg->track; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; char **row; int rowOffset; struct linkedFeaturesSeries *lfsList = NULL, *lfs; char optionScoreStr[256]; /* Option - score filter */ -safef(optionScoreStr, sizeof(optionScoreStr), "%s.%s", table,SCORE_FILTER); // Special case where getScoreFilterClause is too much trouble -int optionScore = cartUsualInt(cart, optionScoreStr, 0); // Special case where CloserToHome not appropriate +// Special case where getScoreFilterClause is too much trouble +safef(optionScoreStr, sizeof(optionScoreStr), "%s.%s", table,SCORE_FILTER); +// Special case where CloserToHome not appropriate +int optionScore = cartUsualInt(cart, optionScoreStr, 0); if (optionScore > 0) { char extraWhere[128]; safef(extraWhere, sizeof(extraWhere), "score >= %d", optionScore); sr = hOrderedRangeQuery(conn, table, chromName, start, end, extraWhere, &rowOffset); } else { sr = hOrderedRangeQuery(conn, table, chromName, start, end, NULL, &rowOffset); } + +char *pslTable = trackDbSetting(tg->tdb, "lfPslTable"); while ((row = sqlNextRow(sr)) != NULL) { struct lfs *lfsbed = lfsLoad(row+rowOffset); - lfs = lfsFromBed(lfsbed); + lfs = lfsFromBed(lfsbed, pslTable); slAddHead(&lfsList, lfs); lfsFree(&lfsbed); } slReverse(&lfsList); sqlFreeResult(&sr); hFreeConn(&conn); return lfsList; } #ifndef GBROWSE void loadBacEndPairs(struct track *tg) /* Load up bac end pairs from table into track items. */ { -tg->items = lfsFromBedsInRange("bacEndPairs", winStart, winEnd, chromName); +tg->items = lfsFromBedsInRange(tg, winStart, winEnd, chromName); } static Color dbRIPColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw dbRIP item */ { struct dbRIP *thisItem = item; if (startsWith("Other", thisItem->polySource)) return tg->ixAltColor; else return MG_BLUE; } static void loadDbRIP(struct track *tg) /* retroposons tracks load methods */ @@ -3711,100 +4237,100 @@ */ if (! (freqLow < freqHi)) { freqLow = 0.0; freqHi = 1.0; } if ((freqLow > 0.0) || (freqHi < 1.0)) needJoin = TRUE; option = cartCgiUsualString(cart, ETHNIC_GROUP, ETHNIC_GROUP_DEFAULT); if (differentString(option,ETHNIC_GROUP_DEFAULT)) needJoin = TRUE; if (needJoin) { - dyStringPrintf(query, "select %s.* from %s,polyGenotype where ", + sqlDyStringPrintf(query, "select %s.* from %s,polyGenotype where ", tg->table, tg->table); if (differentString(option,ETHNIC_GROUP_DEFAULT)) { char *optionNot = cartCgiUsualString(cart, ETHNIC_GROUP_EXCINC, ETHNIC_NOT_DEFAULT); if (sameWord(optionNot,"include")) { - dyStringPrintf(query, "%s.name=polyGenotype.name and " + sqlDyStringPrintf(query, "%s.name=polyGenotype.name and " "polyGenotype.ethnicGroup=\"%s\" and ", tg->table, option); } else { - dyStringPrintf(query, "%s.name=polyGenotype.name and " + sqlDyStringPrintf(query, "%s.name=polyGenotype.name and " "polyGenotype.ethnicGroup!=\"%s\" and ", tg->table, option); } } if ((freqLow > 0.0) || (freqHi < 1.0)) { dyStringPrintf(query, "polyGenotype.alleleFrequency>=\"%.1f\" and " "polyGenotype.alleleFrequency<=\"%.1f\" and ", freqLow, freqHi); } } else { - dyStringPrintf(query, "select * from %s where ", tg->table); + sqlDyStringPrintf(query, "select * from %s where ", tg->table); } hAddBinToQuery(winStart, winEnd, query); -dyStringPrintf(query, +sqlDyStringPrintf(query, "chrom=\"%s\" AND chromStart<%d AND chromEnd>%d ", chromName, winEnd, winStart); option = cartCgiUsualString(cart, GENO_REGION, GENO_REGION_DEFAULT); if (differentString(option,GENO_REGION_DEFAULT)) - dyStringPrintf(query, " and genoRegion=\"%s\"", option); + sqlDyStringPrintf(query, " and genoRegion=\"%s\"", option); option = cartCgiUsualString(cart, POLY_SOURCE, POLY_SOURCE_DEFAULT); if (differentString(option,POLY_SOURCE_DEFAULT)) { char *ucsc = "UCSC"; char *other = "Other"; char *which; if (sameWord(option,"yes")) which = ucsc; else which = other; - dyStringPrintf(query, " and polySource=\"%s\"", which); + sqlDyStringPrintf(query, " and polySource=\"%s\"", which); } option = cartCgiUsualString(cart, POLY_SUBFAMILY, POLY_SUBFAMILY_DEFAULT); if (differentString(option,POLY_SUBFAMILY_DEFAULT)) - dyStringPrintf(query, " and polySubfamily=\"%s\"", option); + sqlDyStringPrintf(query, " and polySubfamily=\"%s\"", option); option = cartCgiUsualString(cart, dbRIP_DISEASE, DISEASE_DEFAULT); if (differentString(option,DISEASE_DEFAULT)) { if (sameWord(option,"no")) dyStringPrintf(query, " and disease=\"NA\""); else dyStringPrintf(query, " and disease!=\"NA\""); } -dyStringPrintf(query, " group by %s.name", tg->table); +sqlDyStringPrintf(query, " group by %s.name", tg->table); sr = sqlGetResult(conn, dyStringCannibalize(&query)); rowOffset=1; while ((row = sqlNextRow(sr)) != NULL) { loadItem = dbRIPLoad(row+rowOffset); slAddHead(&itemList, loadItem); } sqlFreeResult(&sr); hFreeConn(&conn); slSort(&itemList, bedCmp); tg->items = itemList; } @@ -3839,140 +4365,30 @@ { bedMethods(tg); tg->loadItems = loadDbRIP; tg->itemColor = dbRIPColor; tg->itemNameColor = dbRIPColor; tg->itemLabelColor = dbRIPColor; } void bacEndPairsMethods(struct track *tg) /* Fill in track methods for linked features.series */ { linkedFeaturesSeriesMethods(tg); tg->loadItems = loadBacEndPairs; } - -void loadBacEndPairsBad(struct track *tg) -/* Load up fosmid end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("bacEndPairsBad", winStart, winEnd, chromName); -} - - -void bacEndPairsBadMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadBacEndPairsBad; -} - -void loadBacEndPairsLong(struct track *tg) -/* Load up BAC end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("bacEndPairsLong", winStart, winEnd, chromName); -} - - -void bacEndPairsLongMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadBacEndPairsLong; -} - -void loadBacEndSingles(struct track *tg) -/* Load up BAC end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("bacEndSingles", winStart, winEnd, chromName); -} - -void bacEndSinglesMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadBacEndSingles; -} - -void loadFosEndPairs(struct track *tg) -/* Load up fosmid end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("fosEndPairs", winStart, winEnd, chromName); -} - -void fosEndPairsMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadFosEndPairs; -} - -void loadFosEndPairsBad(struct track *tg) -/* Load up fosmid end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("fosEndPairsBad", winStart, winEnd, chromName); -} - - -void fosEndPairsBadMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadFosEndPairsBad; -} - -void loadFosEndPairsLong(struct track *tg) -/* Load up fosmid end pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("fosEndPairsLong", winStart, winEnd, chromName); -} - - -void fosEndPairsLongMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadFosEndPairsLong; -} - -void loadEarlyRep(struct track *tg) -/* Load up early replication cosmid pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("earlyRep", winStart, winEnd, chromName); -} - -void earlyRepMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadEarlyRep; -} - - -void loadEarlyRepBad(struct track *tg) -/* Load up bad early replication pairs from table into track items. */ -{ -tg->items = lfsFromBedsInRange("earlyRepBad", winStart, winEnd, chromName); -} - - -void earlyRepBadMethods(struct track *tg) -/* Fill in track methods for linked features.series */ -{ -linkedFeaturesSeriesMethods(tg); -tg->loadItems = loadEarlyRepBad; -} #endif /* GBROWSE */ // The following few functions are shared by GAD, OMIM, DECIPHER, Superfamily. // Those tracks need an extra label derived from item name -- the extra label // is used as mouseover text for each item, and appears to the immediate left // of the feature in full mode. struct bedPlusLabel { struct bed bed; // inline, so struct bedPlusLabel * can be cast to struct bed *. char *label; }; typedef char *labelFromNameFunction(char *name); @@ -4092,108 +4508,115 @@ unsigned *ends = gp->exonEnds; int i, blockCount = gp->exonCount; for (i=0; i<blockCount; ++i) { AllocVar(sf); sf->start = starts[i]; sf->end = ends[i]; sf->grayIx = grayIx; slAddHead(&sfList, sf); } slReverse(&sfList); return sfList; } +struct linkedFeatures *linkedFeaturesFromGenePred(struct track *tg, struct genePred *gp, boolean extra) +/* construct a linkedFeatures object from a genePred */ +{ +int grayIx = maxShade; +struct linkedFeatures *lf; +AllocVar(lf); +lf->grayIx = grayIx; +lf->name = cloneString(gp->name); +if (extra && gp->name2) + lf->extra = cloneString(gp->name2); +lf->orientation = orientFromChar(gp->strand[0]); + +lf->components = sfFromGenePred(gp, grayIx); + +if (tg->itemAttrTbl != NULL) + lf->itemAttr = itemAttrTblGet(tg->itemAttrTbl, gp->name, + gp->chrom, gp->txStart, gp->txEnd); + +linkedFeaturesBoundsAndGrays(lf); + +if (gp->cdsStart >= gp->cdsEnd) + { + lf->tallStart = gp->txEnd; + lf->tallEnd = gp->txEnd; + } +else + { + lf->tallStart = gp->cdsStart; + lf->tallEnd = gp->cdsEnd; + } +// Don't free gp; it might be used in the drawing phase by baseColor code. +lf->original = gp; +return lf; +} static struct linkedFeatures *connectedLfFromGenePredInRangeExtra( struct track *tg, struct sqlConnection *conn, char *table, char *chrom, int start, int end, boolean extra) /* Return linked features from range of a gene prediction table after * we have already connected to database. Optinally Set lf extra to * gene pred name2, to display gene name instead of transcript ID.*/ { -struct linkedFeatures *lfList = NULL, *lf; -int grayIx = maxShade; +struct linkedFeatures *lfList = NULL; struct genePredReader *gpr = NULL; struct genePred *gp = NULL; boolean nmdTrackFilter = sameString(trackDbSettingOrDefault(tg->tdb, "nmdFilter", "off"), "on"); char varName[SMALLBUF]; safef(varName, sizeof(varName), "%s.%s", table, HIDE_NONCODING_SUFFIX); boolean hideNoncoding = cartUsualBoolean(cart, varName, HIDE_NONCODING_DEFAULT); // TODO: Use cartUsualBooleanClosestToHome if tableName == tg->tdb->track boolean doNmd = FALSE; char buff[256]; safef(buff, sizeof(buff), "hgt.%s.nmdFilter", tg->track); /* Should we remove items that appear to be targets for nonsense * mediated decay? */ if(nmdTrackFilter) doNmd = cartUsualBoolean(cart, buff, FALSE); if (tg->itemAttrTbl != NULL) itemAttrTblLoad(tg->itemAttrTbl, conn, chrom, start, end); char *noncodingClause = (hideNoncoding ? "cdsStart != cdsEnd" : NULL); gpr = genePredReaderRangeQuery(conn, table, chrom, start, end, noncodingClause); while ((gp = genePredReaderNext(gpr)) != NULL) { if (doNmd && genePredNmdTarget(gp)) { genePredFree(&gp); - continue; - } - AllocVar(lf); - lf->grayIx = grayIx; - lf->name = cloneString(gp->name); - if (extra && gp->name2) - lf->extra = cloneString(gp->name2); - lf->orientation = orientFromChar(gp->strand[0]); - - lf->components = sfFromGenePred(gp, grayIx); - - if (tg->itemAttrTbl != NULL) - lf->itemAttr = itemAttrTblGet(tg->itemAttrTbl, gp->name, - gp->chrom, gp->txStart, gp->txEnd); - - linkedFeaturesBoundsAndGrays(lf); - - if (gp->cdsStart >= gp->cdsEnd) - { - lf->tallStart = gp->txEnd; - lf->tallEnd = gp->txEnd; } else { - lf->tallStart = gp->cdsStart; - lf->tallEnd = gp->cdsEnd; + slAddHead(&lfList, linkedFeaturesFromGenePred(tg, gp, extra)); } - // Don't free gp; it might be used in the drawing phase by baseColor code. - lf->original = gp; - slAddHead(&lfList, lf); } slReverse(&lfList); genePredReaderFree(&gpr); if (tg->visibility != tvDense) slSort(&lfList, linkedFeaturesCmpStart); return lfList; } -struct linkedFeatures *connectedLfFromGenePredInRange( - struct track *tg, struct sqlConnection *conn, char *table, - char *chrom, int start, int end) +struct linkedFeatures *connectedLfFromGenePredInRange(struct track *tg, struct sqlConnection *conn, + char *table, char *chrom, int start, int end) /* Return linked features from range of a gene prediction table after * we have already connected to database. */ { return connectedLfFromGenePredInRangeExtra(tg, conn, table, chrom, start, end, FALSE); } struct linkedFeatures *lfFromGenePredInRange(struct track *tg, char *table, char *chrom, int start, int end) /* Return linked features from range of a gene prediction table. */ { struct linkedFeatures *lfList = NULL; struct sqlConnection *conn = hAllocConn(database); lfList = connectedLfFromGenePredInRange(tg, conn, table, chrom, start, end); hFreeConn(&conn); @@ -4232,148 +4655,63 @@ /* Make track of full length mRNAs. */ { tg->itemName = genieName; } static struct dyString *genePredClassFilterBySetQuery(struct track *tg, char *classTable, filterBy_t *filterBySet, struct linkedFeatures *lf) /* construct the query for a standard genePred class filterBtSet */ { char *clause = filterBySetClause(filterBySet); if (clause == NULL) return NULL; // don't care about a column value here, just if it exists, so get a constant char *nameCol = trackDbSettingOrDefault(tg->tdb, GENEPRED_CLASS_NAME_COLUMN, GENEPRED_CLASS_NAME_COLUMN_DEFAULT); -struct dyString *dyQuery = dyStringCreate("select 1 from %s where %s = \"%s\" and ", classTable, nameCol, lf->name); +struct dyString *dyQuery = sqlDyStringCreate("select 1 from %s where %s = \"%s\" and ", classTable, nameCol, lf->name); dyStringAppend(dyQuery, clause); freeMem(clause); return dyQuery; } -static void gencodeFilterByMethodChoice(struct dyString *dyClause, char *choice) -/* add compared for a choice for special case of GENCODE transcript method. */ -{ -if (sameString(choice, "manual")) - dyStringAppend(dyClause, "(transSrc.source like \"%havana%\")"); -else if (sameString(choice, "automatic")) - dyStringAppend(dyClause, "(transSrc.source like \"%ensembl%\")"); -else if (sameString(choice, "manual_only")) - dyStringAppend(dyClause, "(transSrc.source like \"%havana%\") and (transSrc.source not like \"%ensembl%\")"); -else if (sameString(choice, "automatic_only")) - dyStringAppend(dyClause, "(transSrc.source like \"%ensembl%\") and (transSrc.source not like \"%havana%\")"); -else - errAbort("BUG: filterByMethodChoice missing choice: \"%s\"", choice); -} - -static char *gencodeFilterByMethod(filterBy_t *filterBy) -{ -if ((filterBy->slChoices == NULL) || (slNameInList(filterBy->slChoices,"All"))) - return NULL; - -struct dyString *clause = newDyString(256); -struct slName *slChoice = NULL; -dyStringAppend(clause, "(transSrc.transcriptId = attrs.transcriptId) and "); -boolean first = TRUE; -for(slChoice = filterBy->slChoices; slChoice != NULL; slChoice = slChoice->next) - { - if(!first) - dyStringPrintf(clause, " or "); - first = FALSE; - gencodeFilterByMethodChoice(clause, slChoice->name); - } -return dyStringCannibalize(&clause); -} - -static void gencodeFilterBy(filterBy_t *filterBy, struct dyString *where) -/* handle adding on filterBy clause for gencode */ -{ -char *clause; -if (sameString(filterBy->column, "transcriptMethod")) - clause = gencodeFilterByMethod(filterBy); -else - clause = filterByClause(filterBy); -if (clause != NULL) - { - dyStringPrintf(where, " and (%s)", clause); - freeMem(clause); - } -} - -static struct dyString *gencodeFilterBySetQueryWhere(struct track *tg, filterBy_t *filterBySet) -/* build where clause based on filters, or NULL if none */ -{ -struct dyString *where = dyStringNew(0); -filterBy_t *filterBy; -for (filterBy = filterBySet;filterBy != NULL; filterBy = filterBy->next) - gencodeFilterBy(filterBy, where); -if (dyStringLen(where) == 0) - dyStringFree(&where); -return where; -} - -static struct dyString *gencodeFilterBySetQuery(struct track *tg, filterBy_t *filterBySet, struct linkedFeatures *lf) -/* construct the query for GENCODE filterBySet */ -{ -struct dyString *where = gencodeFilterBySetQueryWhere(tg, filterBySet); -if (where == NULL) - return NULL; -char *attrsTbl = trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeAttrs"); -char *srcTbl = trackDbRequiredSetting(tg->tdb, "wgEncodeGencodeTranscriptSource"); -struct dyString *dyQuery = dyStringCreate("select 1 from %s attrs, %s transSrc where (attrs.transcriptId = \"%s\") %s", attrsTbl, srcTbl, lf->name, where->string); -dyStringFree(&where); -return dyQuery; -} - static boolean genePredClassFilterBySet(struct track *tg, char *classTable, filterBy_t *filterBySet, struct linkedFeatures *lf) /* Check if an item passes a filterBySet filter */ { -struct dyString *dyQuery = NULL; -if (trackDbSetting(tg->tdb, "wgEncodeGencodeVersion") != NULL) - { - if (startsWith("wgEncodeGencodeBasic", tg->tdb->track) - || startsWith("wgEncodeGencodeComp", tg->tdb->track) - || startsWith("wgEncodeGencode2wayConsPseudo", tg->tdb->track) - || startsWith("wgEncodeGencodePseudoGene", tg->tdb->track)) - dyQuery = gencodeFilterBySetQuery(tg, filterBySet, lf); - } -else - dyQuery = genePredClassFilterBySetQuery(tg, classTable, filterBySet, lf); +struct dyString *dyQuery = genePredClassFilterBySetQuery(tg, classTable, filterBySet, lf); if (dyQuery == NULL) return TRUE; - struct sqlConnection *conn = hAllocConn(database); boolean passesThroughFilter = sqlQuickNum(conn, dyQuery->string); dyStringFree(&dyQuery); hFreeConn(&conn); return passesThroughFilter; } static boolean genePredClassFilterAcembly(struct track *tg, char *classTable, struct linkedFeatures *lf) /* Check if an item passes a filterBySet filter */ { char *classString = addSuffix(tg->track, ".type"); char *classType = cartUsualString(cart, classString, acemblyEnumToString(0)); freeMem(classString); enum acemblyOptEnum ct = acemblyStringToEnum(classType); if (ct == acemblyAll) return TRUE; struct sqlConnection *conn = hAllocConn(database); char query[1024]; -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select 1 from %s where (name = \"%s\") and (class = \"%s\")", classTable, lf->name, classType); boolean passesThroughFilter = sqlQuickNum(conn, query); hFreeConn(&conn); return passesThroughFilter; } boolean genePredClassFilter(struct track *tg, void *item) /* Returns true if an item should be added to the filter. */ { struct linkedFeatures *lf = item; char *classTable = trackDbSetting(tg->tdb, GENEPRED_CLASS_TBL); if (classTable != NULL && hTableExists(database, classTable)) { filterBy_t *filterBySet = filterBySetGet(tg->tdb,cart,NULL); @@ -4407,49 +4745,49 @@ void lookupKnownNames(struct linkedFeatures *lfList) /* This converts the Genie ID to the HUGO name where possible. */ { struct linkedFeatures *lf; char query[256]; struct sqlConnection *conn = hAllocConn(database); if (hTableExists(database, "knownMore")) { struct knownMore *km; struct sqlResult *sr; char **row; for (lf = lfList; lf != NULL; lf = lf->next) { - sprintf(query, "select * from knownMore where transId = '%s'", lf->name); + sqlSafef(query, sizeof query, "select * from knownMore where transId = '%s'", lf->name); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { km = knownMoreLoad(row); lf->name = cloneString(km->name); if (km->omimId) lf->extra = km; else knownMoreFree(&km); } sqlFreeResult(&sr); } } else if (hTableExists(database, "knownInfo")) { for (lf = lfList; lf != NULL; lf = lf->next) { - sprintf(query, "select name from knownInfo where transId = '%s'", lf->name); + sqlSafef(query, sizeof query, "select name from knownInfo where transId = '%s'", lf->name); sqlQuickQuery(conn, query, lf->name, sizeof(lf->name)); } } hFreeConn(&conn); } void loadGenieKnown(struct track *tg) /* Load up Genie known genes. */ { tg->items = lfFromGenePredInRange(tg, "genieKnown", chromName, winStart, winEnd); if (limitVisibility(tg) == tvFull) { lookupKnownNames(tg->items); } } @@ -4474,31 +4812,31 @@ void genieKnownMethods(struct track *tg) /* Make track of known genes. */ { tg->loadItems = loadGenieKnown; tg->itemName = genieName; tg->itemColor = genieKnownColor; } char *hg17KgName(struct track *tg, void *item) { static char cat[128]; struct linkedFeatures *lf = item; if (lf->extra != NULL) { - sprintf(cat,"%s",(char *)lf->extra); + safef(cat, sizeof cat, "%s",(char *)lf->extra); return cat; } else return lf->name; } char *hg17KgMapName(struct track *tg, void *item) /* Return un-abbreviated gene name. */ { struct linkedFeatures *lf = item; return lf->name; } void lookupHg17KgNames(struct linkedFeatures *lfList) /* This converts the known gene ID to a gene symbol */ @@ -4520,52 +4858,52 @@ boolean useProtDisplayId = sameString(hg17KgLabel, "UniProt Display ID") || sameString(hg17KgLabel, "all"); boolean useMimId = sameString(hg17KgLabel, "OMIM ID") || sameString(hg17KgLabel, "all"); boolean useAll = sameString(hg17KgLabel, "all"); if (hTableExists(database, "kgXref")) { for (lf = lfList; lf != NULL; lf = lf->next) { struct dyString *name = dyStringNew(SMALLDYBUF); if (useGeneSymbol) { - sprintf(cond_str, "kgID='%s'", lf->name); + sqlSafefFrag(cond_str, sizeof cond_str, "kgID='%s'", lf->name); geneSymbol = sqlGetField("hg17", "kgXref", "geneSymbol", cond_str); if (geneSymbol != NULL) { dyStringAppend(name, geneSymbol); if (useAll) dyStringAppendC(name, '/'); } } if (useKgId) { dyStringAppend(name, lf->name); if (useAll) dyStringAppendC(name, '/'); } if (useProtDisplayId) { - safef(cond_str, sizeof(cond_str), "kgID='%s'", lf->name); + sqlSafefFrag(cond_str, sizeof(cond_str), "kgID='%s'", lf->name); protDisplayId = sqlGetField("hg17", "kgXref", "spDisplayID", cond_str); dyStringAppend(name, protDisplayId); } if (useMimId && hTableExists(database, "refLink")) { - safef(cond_str, sizeof(cond_str), "select cast(refLink.omimId as char) from kgXref,refLink where kgID = '%s' and kgXref.refseq = refLink.mrnaAcc and refLink.omimId != 0", lf->name); + sqlSafef(cond_str, sizeof(cond_str), "select cast(refLink.omimId as char) from kgXref,refLink where kgID = '%s' and kgXref.refseq = refLink.mrnaAcc and refLink.omimId != 0", lf->name); mimId = sqlQuickString(conn, cond_str); if (mimId) dyStringAppend(name, mimId); } lf->extra = dyStringCannibalize(&name); } } hFreeConn(&conn); } void loadHg17Kg(struct track *tg) /* Load up known genes. */ { enum trackVisibility vis = tg->visibility; tg->items = lfFromGenePredInRange(tg, "hg17Kg", chromName, winStart, winEnd); @@ -4576,41 +4914,41 @@ limitVisibility(tg); } void hg17KgMethods(struct track *tg) /* Make track of known genes. */ { tg->loadItems = loadHg17Kg; tg->itemName = hg17KgName; tg->mapItemName = hg17KgMapName; } char *h1n1SeqName(struct track *tg, void *item) { struct linkedFeatures *lf = item; struct sqlConnection *conn = hAllocConn(database); -char query[256]; +char query[256], temp[256]; char *strain = NULL; char *chp; -safef(query, sizeof(query), "select strain from h1n1SeqXref where seqId = '%s'", lf->name); +sqlSafef(query, sizeof(query), "select strain from h1n1SeqXref where seqId = '%s'", lf->name); strain = sqlQuickString(conn, query); chp = strstr(strain, "/2009"); if (chp != NULL) *chp = '\0'; hFreeConn(&conn); -safef(query, sizeof(query), "%s %s", strain+2, lf->name); -return(strdup(query)); +safef(temp, sizeof(temp), "%s %s", strain+2, lf->name); +return(strdup(temp)); } char *knownGeneName(struct track *tg, void *item) { static char cat[128]; struct linkedFeatures *lf = item; if (lf->extra != NULL) { safef(cat, sizeof(cat), "%s",((struct knownGenesExtra *)(lf->extra))->name); return cat; } else return lf->name; } @@ -4671,64 +5009,64 @@ !endsWith(label->name, omimLabel) ) { useGeneSymbol = TRUE; cartRemove(cart, label->name); } } for (lf = lfList; lf != NULL; lf = lf->next) { struct dyString *name = dyStringNew(SMALLDYBUF); struct knownGenesExtra *kgE; AllocVar(kgE); labelStarted = FALSE; /* reset between items */ if (useGeneSymbol) { - sprintf(cond_str, "kgID='%s'", lf->name); + sqlSafefFrag(cond_str, sizeof cond_str,"kgID='%s'", lf->name); geneSymbol = sqlGetField(database, "kgXref", "geneSymbol", cond_str); if (geneSymbol != NULL) { dyStringAppend(name, geneSymbol); } labelStarted = TRUE; } if (useKgId) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; dyStringAppend(name, lf->name); } if (useProtDisplayId) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; if (lf->extra != NULL) { dyStringAppend(name, (char *)lf->extra); } else { - safef(cond_str, sizeof(cond_str), "kgID='%s'", lf->name); + sqlSafefFrag(cond_str, sizeof(cond_str), "kgID='%s'", lf->name); protDisplayId = sqlGetField(database, "kgXref", "spDisplayID", cond_str); dyStringAppend(name, protDisplayId); } } if (useMimId && hTableExists(database, "refLink")) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; - safef(cond_str, sizeof(cond_str), "select cast(refLink.omimId as char) from kgXref,refLink where kgID = '%s' and kgXref.refseq = refLink.mrnaAcc and refLink.omimId != 0", lf->name); + sqlSafef(cond_str, sizeof(cond_str), "select cast(refLink.omimId as char) from kgXref,refLink where kgID = '%s' and kgXref.refseq = refLink.mrnaAcc and refLink.omimId != 0", lf->name); mimId = sqlQuickString(conn, cond_str); if (mimId) dyStringAppend(name, mimId); } /* should this be a hash instead? */ kgE->name = dyStringCannibalize(&name); kgE->hgg_prot = lf->extra; lf->extra = kgE; } } hFreeConn(&conn); } struct linkedFeatures *stripShortLinkedFeatures(struct linkedFeatures *list) /* Remove linked features with no tall component from list. */ @@ -4767,31 +5105,31 @@ safef(varName, sizeof(varName), "%s.show.noncoding", tdb->track); boolean showNoncoding = cartUsualBoolean(cart, varName, TRUE); safef(varName, sizeof(varName), "%s.show.spliceVariants", tdb->track); boolean showSpliceVariants = cartUsualBoolean(cart, varName, TRUE); if (!showNoncoding) tg->items = stripShortLinkedFeatures(tg->items); if (!showSpliceVariants) { char *canonicalTable = trackDbSettingOrDefault(tdb, "canonicalTable", "knownCanonical"); if (hTableExists(database, canonicalTable)) { /* Create hash of items in canonical table in region. */ struct sqlConnection *conn = hAllocConn(database); struct hash *hash = hashNew(0); char query[512]; - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select transcript from %s where chromStart < %d && chromEnd > %d", canonicalTable, winEnd, winStart); struct sqlResult *sr = sqlGetResult(conn, query); char **row; while ((row = sqlNextRow(sr)) != NULL) hashAdd(hash, row[0], NULL); sqlFreeResult(&sr); hFreeConn(&conn); /* Get rid of non-canonical items. */ tg->items = stripLinkedFeaturesNotInHash(tg->items, hash); hashFree(&hash); } } lookupKnownGeneNames(tg->items); @@ -4825,95 +5163,95 @@ Lightest blue: Eveything else */ lighter.r = (6*normal->r + 4*255) / 10; lighter.g = (6*normal->g + 4*255) / 10; lighter.b = (6*normal->b + 4*255) / 10; lightest.r = (1*normal->r + 2*255) / 3; lightest.g = (1*normal->g + 2*255) / 3; lightest.b = (1*normal->b + 2*255) / 3; /* set default to the lightest color */ col = hvGfxFindColorIx(hvg, lightest.r, lightest.g, lightest.b); /* set color first according to RefSeq status (if there is a corresponding RefSeq) */ -sprintf(cond_str, "name='%s' ", lf->name); +sqlSafefFrag(cond_str, sizeof cond_str, "name='%s' ", lf->name); refAcc = sqlGetField(database, "refGene", "name", cond_str); if (refAcc != NULL) { if (hTableExists(database, "refSeqStatus")) { - sprintf(query, "select status from refSeqStatus where mrnaAcc = '%s'", refAcc); + sqlSafef(query, sizeof query, "select status from refSeqStatus where mrnaAcc = '%s'", refAcc); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (startsWith("Reviewed", row[0]) || startsWith("Validated", row[0])) { /* Use the usual color */ col = tg->ixColor; } else { col = hvGfxFindColorIx(hvg, lighter.r, lighter.g, lighter.b); } } sqlFreeResult(&sr); } } /* set to dark blue if there is a corresponding Swiss-Prot protein */ -sprintf(cond_str, "name='%s'", (char *)(lf->name)); +sqlSafefFrag(cond_str, sizeof cond_str, "name='%s'", lf->name); proteinID= sqlGetField(database, "knownGene", "proteinID", cond_str); if (proteinID != NULL && protDbName != NULL) { - sprintf(cond_str, "displayID='%s' AND biodatabaseID=1 ", proteinID); - ans= sqlGetField(protDbName, "spXref2", "displayID", cond_str); + sqlSafefFrag(cond_str, sizeof cond_str, "displayID='%s' AND biodatabaseID=1 ", proteinID); + ans= sqlGetField(protDbName, "spXref3", "displayID", cond_str); if (ans != NULL) { col = tg->ixColor; } } /* if a corresponding PDB entry exists, set it to black */ if (protDbName != NULL) { - sprintf(cond_str, "sp='%s'", proteinID); + sqlSafefFrag(cond_str, sizeof cond_str, "sp='%s'", proteinID); pdbID= sqlGetField(protDbName, "pdbSP", "pdb", cond_str); } if (pdbID != NULL) { col = MG_BLACK; } hFreeConn(&conn); return(col); } Color knownGeneColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color for a known gene item - looking it up in table in * newer versions, and calculating it on fly in later versions. */ { if (hTableExists(database, "kgColor")) { struct linkedFeatures *lf = item; int colIx = MG_BLUE; struct sqlConnection *conn = hAllocConn(database); char query[512]; - safef(query, sizeof(query), "select r,g,b from kgColor where kgID='%s'", + sqlSafef(query, sizeof(query), "select r,g,b from kgColor where kgID='%s'", lf->name); struct sqlResult *sr = sqlGetResult(conn, query); char **row = sqlNextRow(sr); if (row != NULL) colIx = hvGfxFindColorIx(hvg, sqlUnsigned(row[0]), sqlUnsigned(row[1]), sqlUnsigned(row[2])); sqlFreeResult(&sr); hFreeConn(&conn); return colIx; } else return knownGeneColorCalc(tg, item, hvg); } void knownGeneMethods(struct track *tg) /* Make track of known genes. */ @@ -4931,115 +5269,115 @@ /* use loadGenePredWithName2 instead of loadKnownGene to pick up proteinID */ tg->itemName = h1n1SeqName; } char *superfamilyName(struct track *tg, void *item) /* Return map name of the track item (used by hgc). */ { char *name; char *proteinName; struct sqlConnection *conn = hAllocConn(database); char conditionStr[256]; struct bed *sw = item; // This is necessary because Ensembl kept changing their xref table definition -sprintf(conditionStr, "transcript_name='%s'", sw->name); +sqlSafef(conditionStr, sizeof conditionStr, "transcript_name='%s'", sw->name); if (hTableExists(database, "ensGeneXref")) { proteinName = sqlGetField(database, "ensGeneXref", "translation_name", conditionStr); } else if (hTableExists(database, "ensemblXref2")) { proteinName = sqlGetField(database, "ensemblXref2", "translation_name", conditionStr); } else { if (hTableExists(database, "ensemblXref")) { proteinName = sqlGetField(database, "ensemblXref", "translation_name", conditionStr); } else { if (hTableExists(database, "ensTranscript")) { proteinName = sqlGetField(database,"ensTranscript","translation_name",conditionStr); } else { if (hTableExists(database, "ensemblXref3")) { - sprintf(conditionStr, "transcript='%s'", sw->name); + sqlSafef(conditionStr, sizeof conditionStr, "transcript='%s'", sw->name); proteinName = sqlGetField(database, "ensemblXref3", "protein", conditionStr); } else { proteinName = cloneString(""); } } } } name = cloneString(proteinName); hFreeConn(&conn); return(name); } static char *superfamilyNameLong(char *name) /* Return domain names of an entry of a Superfamily track item, each item may have multiple names due to possibility of multiple domains. */ { char query[256]; -safef(query, sizeof(query), "select description from sfDescription where name='%s';", name); +sqlSafef(query, sizeof(query), "select description from sfDescription where name='%s';", name); return collapseRowsFromQuery(query, "; ", 100); } static void superfamilyLoad(struct track *tg) /* Load superfamily items; in addition to items, store long description for mouseover/full mode. */ { bedPlusLabelLoad(tg, superfamilyNameLong); } void superfamilyMethods(struct track *tg) /* Fill in methods for (simple) bed tracks. */ { tg->loadItems = superfamilyLoad; tg->drawItemAt = bedPlusLabelDrawAt; tg->mapItem = bedPlusLabelMapItem; tg->itemName = superfamilyName; tg->mapItemName = superfamilyName; tg->nextPrevExon = simpleBedNextPrevEdge; } static char *gadDiseaseClassList(char *name) /* Return list of diseases associated with a GAD entry */ { char query[256]; -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select distinct diseaseClassCode from gadAll " "where geneSymbol='%s' and association = 'Y' order by diseaseClassCode", name); return collapseRowsFromQuery(query, ",", 20); } static char *gadDiseaseList(char *name) /* Return list of diseases associated with a GAD entry */ { char query[256]; -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select distinct broadPhen from gadAll where geneSymbol='%s' and association = 'Y' " "order by broadPhen", name); return collapseRowsFromQuery(query, "; ", 20); } static void gadLoad(struct track *tg) /* Load GAD items as bed + label (used for mouseover; different label in draw routine!) */ { bedPlusLabelLoad(tg, gadDiseaseList); } static void gadDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw a single GAD item at position with extra label in full mode. @@ -5058,83 +5396,83 @@ hvGfxBox(hvg, x1, y, w, heightPer, color); if (vis == tvFull) { // New text for label in full mode: char *sDiseaseClasses = gadDiseaseClassList(bed->name); int textWidth = mgFontStringWidth(font, sDiseaseClasses); hvGfxTextRight(hvg, x1-textWidth-2, y, textWidth, heightPer, MG_BLACK, font, sDiseaseClasses); } } static char *decipherPhenotypeList(char *name) /* Return list of diseases associated with a DECIPHER entry */ { char query[256]; -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select distinct phenotype from decipherRaw where id='%s' order by phenotype", name); return collapseRowsFromQuery(query, "; ", 20); } void decipherLoad(struct track *tg) /* Load DECIPHER items with extra labels from decipherPhenotypeList. */ { bedPlusLabelLoad(tg, decipherPhenotypeList); } Color decipherColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw DECIPHER entry */ { struct bed *bed = item; int col = tg->ixColor; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr; char **row; char query[256]; char cond_str[256]; char *decipherId = NULL; /* color scheme: RED: If the entry is a deletion (mean ratio < 0) BLUE: If the entry is a duplication (mean ratio > 0) */ -safef(cond_str, sizeof(cond_str),"name='%s' ", bed->name); +sqlSafefFrag(cond_str, sizeof(cond_str),"name='%s' ", bed->name); decipherId = sqlGetField(database, "decipher", "name", cond_str); if (decipherId != NULL) { if (hTableExists(database, "decipherRaw")) { - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select mean_ratio > 0 from decipherRaw where id = '%s' and start=%d and end=%d", decipherId, bed->chromStart+1, bed->chromEnd); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (sameWord(row[0], "1")) { col = MG_BLUE; } else { col = MG_RED; } } sqlFreeResult(&sr); /* add more logic here to check for mean_ratio = 0 (which is a problem to be fixed by DECIPHER */ - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select mean_ratio = 0 from decipherRaw where id = '%s'", decipherId); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (sameWord(row[0], "1")) { col = MG_GRAY; } } sqlFreeResult(&sr); } } hFreeConn(&conn); return(col); } @@ -5194,31 +5532,31 @@ if (s > e) return; int x1 = round((s-winStart)*scale) + xOff; int x2 = round((e-winStart)*scale) + xOff; int w = x2 - x1; if (w < 1) w = 1; hvGfxBox(hvg, x1, y, w, heightPer, color); if (tg->drawName && vis != tvSquish) { /* get description from rgdQtlLink table */ struct sqlConnection *conn = hAllocConn(database); char cond_str[256]; char linkTable[256]; safef(linkTable, sizeof(linkTable), "%sLink", tg->table); - safef(cond_str, sizeof(cond_str), "name='%s'", tg->itemName(tg, bed)); + sqlSafefFrag(cond_str, sizeof(cond_str), "name='%s'", tg->itemName(tg, bed)); char *s = sqlGetField(database, linkTable, "description", cond_str); hFreeConn(&conn); if (s == NULL) s = bed->name; /* chop off text starting from " (human)" */ char *chp = strstr(s, " (human)"); if (chp != NULL) *chp = '\0'; /* adjust range of text display to fit within the display window */ int x3=x1, x4=x2; if (x3 < xOff) x3 = xOff; if (x4 > (insideWidth + xOff)) x4 = insideWidth + xOff; int w2 = x4 - x3; /* calculate how many characters we can squeeze into box */ int boxWidth = w2 / mgFontCharWidth(font, 'm'); int textWidth = strlen(s); @@ -5277,82 +5615,78 @@ } char *getOrganism(struct sqlConnection *conn, char *acc) /* lookup the organism for an mrna, or NULL if not found */ { // cache results, as this can be called a lot of times trying to pack tracks and test // for row overflow static struct hash *cache = NULL; if (cache == NULL) cache = hashNew(0); // N.B. NULL is a valid value in the cache struct hashEl *cacheEl = hashLookup(cache, acc); if (cacheEl == NULL) { char query[256]; - sprintf(query, "select organism.name from gbCdnaInfo,organism where gbCdnaInfo.acc = '%s' and gbCdnaInfo.organism = organism.id", acc); + sqlSafef(query, sizeof query, + "select organism.name from gbCdnaInfo,organism where gbCdnaInfo.acc = '%s' and gbCdnaInfo.organism = organism.id", acc); char *org = sqlQuickString(conn, query); if ((org != NULL) && (org[0] == '\0')) org = NULL; cacheEl = hashAdd(cache, acc, org); } return cacheEl->val; } char *getOrganismShort(struct sqlConnection *conn, char *acc) /* lookup the organism for an mrna, or NULL if not found. This will * only return the genus, and only the first seven letters of that. * WARNING: static return */ { return orgShortName(getOrganism(conn, acc)); } char *getGeneName(struct sqlConnection *conn, char *acc) /* get geneName from refLink or NULL if not found. * WARNING: static return */ { static char nameBuf[256]; char query[256], *name = NULL; if (hTableExists(database, "refLink")) { - sprintf(query, "select name from refLink where mrnaAcc = '%s'", acc); + /* remove the version number if any */ + static char accBuf[1024]; + safecpy(accBuf, sizeof accBuf, acc); + chopSuffix(accBuf); + + sqlSafef(query, sizeof query, "select name from refLink where mrnaAcc = '%s'", accBuf); name = sqlQuickQuery(conn, query, nameBuf, sizeof(nameBuf)); if ((name != NULL) && (name[0] == '\0')) name = NULL; } return name; } -char *gencodeGeneName(struct track *tg, void *item) -/* Get name to use for Gencode gene item. */ -{ -struct linkedFeatures *lf = item; -if (lf->extra != NULL) - return lf->extra; -else - return lf->name; -} - char *getRgdGene2Symbol(struct sqlConnection *conn, char *acc) /* get gene symbol from rgdGene2ToSymbol or NULL if not found. * WARNING: static return */ { static char symbolBuf[256]; char query[256], *symbol = NULL; if (hTableExists(database, "rgdGene2ToSymbol")) { - sprintf(query, "select geneSymbol from rgdGene2ToSymbol where rgdId = '%s'", acc); + sqlSafef(query, sizeof query, "select geneSymbol from rgdGene2ToSymbol where rgdId = '%s'", acc); symbol = sqlQuickQuery(conn, query, symbolBuf, sizeof(symbolBuf)); if ((symbol != NULL) && (symbol[0] == '\0')) symbol = NULL; } return symbol; } char *rgdGene2Name(struct track *tg, void *item) /* Get name to use for rgdGene2 item. */ { struct linkedFeatures *lf = item; if (lf->extra != NULL) return lf->extra; else return lf->name; @@ -5441,31 +5775,34 @@ char *refGeneName(struct track *tg, void *item) /* Get name to use for refGene item. */ { struct linkedFeatures *lf = item; if (lf->extra != NULL) return lf->extra; else return lf->name; } char *refGeneMapName(struct track *tg, void *item) /* Return un-abbreviated gene name. */ { struct linkedFeatures *lf = item; -return lf->name; +char buffer[1024]; +safecpy(buffer, sizeof buffer, lf->name); +chopSuffix(buffer); +return cloneString(buffer); } void lookupRefNames(struct track *tg) /* This converts the refSeq accession to a gene name where possible. */ { struct linkedFeatures *lf; struct sqlConnection *conn = hAllocConn(database); boolean isNative = sameString(tg->table, "refGene"); boolean labelStarted = FALSE; boolean useGeneName = FALSE; boolean useAcc = FALSE; boolean useMim = FALSE; struct hashEl *refGeneLabels = cartFindPrefix(cart, (isNative ? "refGene.label" : "xenoRefGene.label")); struct hashEl *label; @@ -5513,31 +5850,31 @@ { dyStringAppend(name, gene); } labelStarted = TRUE; } if (useAcc) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; dyStringAppend(name, lf->name); } if (useMim) { char *mimId; char query[256]; - safef(query, sizeof(query), "select cast(omimId as char) from refLink where mrnaAcc = '%s'", lf->name); + sqlSafef(query, sizeof(query), "select cast(omimId as char) from refLink where mrnaAcc = '%s'", lf->name); mimId = sqlQuickString(conn, query); if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; if (mimId && differentString(mimId, "0")) dyStringAppend(name, mimId); } lf->extra = dyStringCannibalize(&name); } hFreeConn(&conn); } void lookupProteinNames(struct track *tg) /* This converts the knownGene accession to a gene name where possible. */ { struct linkedFeatures *lf; @@ -5573,33 +5910,33 @@ struct sqlResult *sr; char **row; struct sqlConnection *conn = hAllocConn(thisDb); boolean added = FALSE; char *ptr; for (lf = tg->items; lf != NULL; lf = lf->next) { added = FALSE; buffer = needMem(strlen(lf->name) + 1); strcpy(buffer, lf->name); if ((char *)NULL != (ptr = strchr(buffer, '.'))) *ptr = 0; if (!startsWith("blastDm", tg->tdb->track)) - safef(query, sizeof(query), "select geneId, refPos, extra1 from %s where acc = '%s'", blastRef, buffer); + sqlSafef(query, sizeof(query), "select geneId, refPos, extra1 from %s where acc = '%s'", blastRef, buffer); else - safef(query, sizeof(query), "select geneId, refPos from %s where acc = '%s'", blastRef, buffer); + sqlSafef(query, sizeof(query), "select geneId, refPos from %s where acc = '%s'", blastRef, buffer); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { lf->extra = needMem(strlen(lf->name) + strlen(row[0])+ strlen(row[1])+ strlen(row[2]) + 1); if (useGene) { added = TRUE; strcat(lf->extra, row[0]); } if (useAcc ) { if (added) strcat(lf->extra, "/"); added = TRUE; strcat(lf->extra, lf->name); @@ -5690,31 +6027,31 @@ char *thisDb = cloneString(blastRef); char *table; if ((table = strchr(thisDb, '.')) != NULL) { *table++ = 0; if (hTableExists(thisDb, table)) { char query[256]; struct sqlResult *sr; char **row; struct sqlConnection *conn = hAllocConn(database); if ((pos = strchr(acc, '.')) != NULL) *pos = 0; - safef(query, sizeof(query), "select refPos from %s where acc = '%s'", blastRef, buffer); + sqlSafef(query, sizeof(query), "select refPos from %s where acc = '%s'", blastRef, buffer); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (startsWith("chr", row[0]) && ((colon = strchr(row[0], ':')) != NULL)) { *colon = 0; col = getSeqColor(row[0], hvg); } } sqlFreeResult(&sr); hFreeConn(&conn); } } } else @@ -5741,31 +6078,31 @@ Color refGeneColorByStatus(struct track *tg, char *name, struct hvGfx *hvg) /* Get refseq gene color from refSeqStatus. * Reviewed, Validated -> normal, Provisional -> lighter, * Predicted, Inferred(other) -> lightest * If no refSeqStatus, color it normally. */ { int col = tg->ixColor; struct rgbColor *normal = &(tg->color); struct rgbColor lighter, lightest; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr; char **row; char query[256]; -sprintf(query, "select status from refSeqStatus where mrnaAcc = '%s'", +sqlSafef(query, sizeof query, "select status from refSeqStatus where mrnaAcc = '%s'", name); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (startsWith("Reviewed", row[0]) || startsWith("Validated", row[0])) { /* Use the usual color */ } else if (startsWith("Provisional", row[0])) { lighter.r = (6*normal->r + 4*255) / 10; lighter.g = (6*normal->g + 4*255) / 10; lighter.b = (6*normal->b + 4*255) / 10; col = hvGfxFindRgb(hvg, &lighter); } @@ -5817,31 +6154,31 @@ tg->loadItems = loadRgdGene2; tg->itemName = rgdGene2Name; tg->mapItemName = rgdGene2MapName; } boolean filterNonCoding(struct track *tg, void *item) /* Returns TRUE if the item passes the filter */ { char condStr[256]; char *bioType; struct linkedFeatures *lf = item; int i = 0; struct sqlConnection *conn = hAllocConn(database); /* Find the biotype for this item */ -sprintf(condStr, "name='%s'", lf->name); +sqlSafef(condStr, sizeof condStr, "name='%s'", lf->name); bioType = sqlGetField(database, "ensGeneNonCoding", "biotype", condStr); hFreeConn(&conn); /* check for this type in the array and use its index to find whether this type is in the cart and checked for inclusion */ for (i = 0; i < nonCodingTypeDataNameSize; i++) { cartCgiUsualBoolean(cart, nonCodingTypeIncludeStrings[i], TRUE); if (!sameString(nonCodingTypeDataName[i], bioType)) { continue; } return nonCodingTypeIncludeCart[i]; } return TRUE; @@ -5865,31 +6202,31 @@ Color ensGeneNonCodingColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw Ensembl non-coding gene/pseudogene in. */ { char condStr[255]; char *bioType; Color color = {MG_GRAY}; /* Set default to gray */ struct rgbColor hAcaColor = {0, 128, 0}; /* darker green, per request by Weber */ Color hColor; struct sqlConnection *conn; char *name; conn = hAllocConn(database); hColor = hvGfxFindColorIx(hvg, hAcaColor.r, hAcaColor.g, hAcaColor.b); name = tg->itemName(tg, item); -sprintf(condStr, "name='%s'", name); +sqlSafef(condStr, sizeof condStr, "name='%s'", name); bioType = sqlGetField(database, "ensGeneNonCoding", "biotype", condStr); if (sameWord(bioType, "miRNA")) color = MG_RED; if (sameWord(bioType, "misc_RNA")) color = MG_BLACK; if (sameWord(bioType, "snRNA")) color = MG_BLUE; if (sameWord(bioType, "snoRNA")) color = MG_MAGENTA; if (sameWord(bioType, "rRNA")) color = MG_CYAN; if (sameWord(bioType, "scRNA")) color = MG_YELLOW; if (sameWord(bioType, "Mt_tRNA")) color = MG_GREEN; if (sameWord(bioType, "Mt_rRNA")) color = hColor; /* Pseudogenes in the zebrafish will be coloured brown */ if (sameWord(bioType, "pseudogene")) color = hvGfxFindColorIx(hvg, brownColor.r, brownColor.g, brownColor.b); @@ -5900,31 +6237,31 @@ void ensGeneNonCodingMethods(struct track *tg) /* Make track of Ensembl predictions. */ { tg->items = lfFromGenePredInRange(tg, tg->table, chromName, winStart, winEnd); tg->itemColor = ensGeneNonCodingColor; tg->loadItems = loadEnsGeneNonCoding; } int cDnaReadDirectionForMrna(struct sqlConnection *conn, char *acc) /* Return the direction field from the mrna table for accession acc. Return -1 if not in table.*/ { int direction = -1; char query[512]; char buf[SMALLBUF], *s = NULL; -sprintf(query, "select direction from gbCdnaInfo where acc='%s'", acc); +sqlSafef(query, sizeof query, "select direction from gbCdnaInfo where acc='%s'", acc); if ((s = sqlQuickQuery(conn, query, buf, sizeof(buf))) != NULL) { direction = atoi(s); } return direction; } void orientEsts(struct track *tg) /* Orient ESTs from the estOrientInfo table. */ { struct linkedFeatures *lf = NULL, *lfList = tg->items; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; char **row = NULL; int rowOffset = 0; @@ -5950,32 +6287,31 @@ /* Now lookup orientation of each est. */ for(lf = lfList; lf != NULL; lf = lf->next) { estOrient = hashIntValDefault(orientHash, lf->name, 0); if (estOrient < 0) lf->orientation = -1 * lf->orientation; else if (estOrient == 0) lf->orientation = 0; // not known, don't display chevrons } hashFree(&orientHash); } hFreeConn(&conn); } -void linkedFeaturesAverageDenseOrientEst(struct track *tg, - int seqStart, int seqEnd, +void linkedFeaturesAverageDenseOrientEst(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw dense linked features items. */ { if(vis == tvSquish || vis == tvPack || vis == tvFull) orientEsts(tg); if (vis == tvDense) linkedFeaturesDrawAverage(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); else linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } @@ -6050,31 +6386,31 @@ fieldExists = (tblIx > -1) ? TRUE : FALSE; if (fieldExists) dyStringPrintf(dy2, "%s", "confidence"); else { tblIx = sqlFieldIndex(conn, infoTable, "method"); fieldExists = (tblIx > -1) ? TRUE : FALSE; dyStringPrintf(dy2, "%s", "method"); } } if (isNotEmpty(infoTable) && fieldExists) { /* use the value for infoCol defined above */ infoCol = dyStringCannibalize(&dy2); - sprintf(query, "select %s from %s where transcriptId = '%s'", + sqlSafef(query, sizeof query, "select %s from %s where transcriptId = '%s'", infoCol, infoTable, lf->name); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { if (sameWord("Known", row[0]) || sameWord("KNOWN", row[0]) || sameWord("Novel_CDS", row[0]) || sameWord("Novel_Transcript", row[0]) || sameWord("NOVEL", row[0])) { /* Use the usual color (dark blue) */ } else if (sameWord("Putative", row[0]) || sameWord("Ig_Segment", row[0]) || sameWord("PUTATIVE", row[0])) @@ -6109,31 +6445,31 @@ /* Return bdgpGene symbol. */ { struct linkedFeatures *lf = item; char *name = cloneString(lf->name); char infoTable[128]; safef(infoTable, sizeof(infoTable), "%sInfo", tg->table); if (hTableExists(database, infoTable)) { struct sqlConnection *conn = hAllocConn(database); char *symbol = NULL; char *ptr = strchr(name, '-'); char query[256]; char buf[SMALLBUF]; if (ptr != NULL) *ptr = 0; - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select symbol from %s where bdgpName = '%s';", infoTable, name); symbol = sqlQuickQuery(conn, query, buf, sizeof(buf)); hFreeConn(&conn); if (symbol != NULL) { char *ptr = stringIn("{}", symbol); if (ptr != NULL) *ptr = 0; freeMem(name); name = cloneString(symbol); } } return(name); } @@ -6144,59 +6480,59 @@ } char *flyBaseGeneName(struct track *tg, void *item) /* Return symbolic name for FlyBase gene with lookup table for name->symbol * specified in trackDb. */ { struct linkedFeatures *lf = item; char *name = cloneString(lf->name); char *infoTable = trackDbSettingOrDefault(tg->tdb, "symbolTable", ""); if (isNotEmpty(infoTable) && hTableExists(database, infoTable)) { struct sqlConnection *conn = hAllocConn(database); char *symbol = NULL; char query[256]; char buf[SMALLBUF]; - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select symbol from %s where name = '%s';", infoTable, name); symbol = sqlQuickQuery(conn, query, buf, sizeof(buf)); hFreeConn(&conn); if (isNotEmpty(symbol)) { freeMem(name); name = cloneString(symbol); } } return(name); } void flyBaseGeneMethods(struct track *tg) /* Special handling for FlyBase genes. */ { tg->itemName = flyBaseGeneName; } char *sgdGeneName(struct track *tg, void *item) /* Return sgdGene symbol. */ { struct sqlConnection *conn = hAllocConn(database); struct linkedFeatures *lf = item; char *name = lf->name; char *symbol = NULL; char query[256]; char buf[SMALLBUF]; -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select value from sgdToName where name = '%s'", name); symbol = sqlQuickQuery(conn, query, buf, sizeof(buf)); hFreeConn(&conn); if (symbol != NULL) name = symbol; return(cloneString(name)); } void sgdGeneMethods(struct track *tg) /* Special handling for sgdGene items. */ { tg->itemName = sgdGeneName; } void adjustBedScoreGrayLevel(struct trackDb *tdb, struct bed *bed, int scoreMin, int scoreMax) @@ -6215,32 +6551,32 @@ { scoreMinGrayLevel = scoreMin * maxShade/scoreMax; if (scoreMinGrayLevel <= 0) scoreMinGrayLevel = 1; char *setting = trackDbSettingClosestToHome(tdb, MIN_GRAY_LEVEL); cartMinGrayLevel = cartUsualIntClosestToHome(cart, tdb, FALSE, MIN_GRAY_LEVEL, setting ? atoi(setting) : scoreMinGrayLevel); newScoreMin = cartMinGrayLevel * scoreMax/maxShade; prevTrackName = tdb->track; } if (cartMinGrayLevel != scoreMinGrayLevel) { float realScore = (float)(bed->score - scoreMin) / (scoreMax - scoreMin); bed->score = newScoreMin + (realScore * (scoreMax - newScoreMin)) + 0.5; } -else if(scoreMin != 0 && scoreMax == 1000) // Changes gray level even when UI does not allow selecting it. - { +else if (scoreMin != 0 && scoreMax == 1000) // Changes gray level even when + { // UI does not allow selecting it. float realScore = (float)(bed->score) / 1000; bed->score = scoreMin + (realScore * (scoreMax - scoreMin)) + 0.5; } } void bedLoadItemByQuery(struct track *tg, char *table, char *query, ItemLoader loader) /* Generic tg->item loader. If query is NULL use generic hRangeQuery(). */ { struct sqlConnection *conn = hAllocConn(database); int rowOffset = 0; struct sqlResult *sr = NULL; char **row = NULL; struct slList *itemList = NULL, *item = NULL; @@ -6468,31 +6804,31 @@ { bedLoadItem(tg, "isochores", (ItemLoader)isochoresLoad); } void isochoreFree(struct track *tg) /* Free up isochore items. */ { isochoresFreeList((struct isochores**)&tg->items); } char *isochoreName(struct track *tg, void *item) /* Return name of gold track item. */ { struct isochores *iso = item; static char buf[SMALLBUF]; -sprintf(buf, "%3.1f%% GC", 0.1*iso->gcPpt); +safef(buf, sizeof buf, "%3.1f%% GC", 0.1*iso->gcPpt); return buf; } static void isochoreDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw isochore items. */ { struct isochores *item; int y = yOff; int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; int x1,x2,w; boolean isFull = (vis == tvFull); double scale = scaleForPixels(width); @@ -6888,53 +7224,53 @@ /* Make track for simple repeats. */ { tg->loadItems = loadCpgIsland; tg->freeItems = freeCpgIsland; tg->itemColor = cpgIslandColor; } char *rgdGeneItemName(struct track *tg, void *item) /* Return name of RGD gene track item. */ { static char name[32]; struct sqlConnection *conn = hAllocConn(database); struct dyString *ds = newDyString(256); struct linkedFeatures *lf = item; -dyStringPrintf(ds, "select name from rgdGeneLink where refSeq = '%s'", lf->name); +sqlDyStringPrintf(ds, "select name from rgdGeneLink where refSeq = '%s'", lf->name); sqlQuickQuery(conn, ds->string, name, sizeof(name)); freeDyString(&ds); hFreeConn(&conn); return name; } void rgdGeneMethods(struct track *tg) /* Make track for RGD genes. */ { tg->itemName = rgdGeneItemName; } void loadGcPercent(struct track *tg) /* Load up simpleRepeats from database table to track items. */ { struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; char **row; struct gcPercent *itemList = NULL, *item; char query[256]; -sprintf(query, "select * from %s where chrom = '%s' and chromStart<%u and chromEnd>%u", tg->table, +sqlSafef(query, sizeof query, "select * from %s where chrom = '%s' and chromStart<%u and chromEnd>%u", tg->table, chromName, winEnd, winStart); /* Get the frags and load into tg->items. */ sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) { item = gcPercentLoad(row); if (item->gcPpt != 0) { slAddHead(&itemList, item); } else gcPercentFree(&item); } slReverse(&itemList); @@ -6944,31 +7280,31 @@ } void freeGcPercent(struct track *tg) /* Free up isochore items. */ { gcPercentFreeList((struct gcPercent**)&tg->items); } char *gcPercentName(struct track *tg, void *item) /* Return name of gcPercent track item. */ { struct gcPercent *gc = item; static char buf[32]; -sprintf(buf, "%3.1f%% GC", 0.1*gc->gcPpt); +safef(buf, sizeof buf, "%3.1f%% GC", 0.1*gc->gcPpt); return buf; } static int gcPercentMin = 320; static int gcPercentMax = 600; Color gcPercentColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return name of gcPercent track item. */ { struct gcPercent *gc = item; int ppt = gc->gcPpt; int grayLevel; grayLevel = grayInRange(ppt, gcPercentMin, gcPercentMax); return shadesOfGray[grayLevel]; @@ -7046,40 +7382,40 @@ void freeRecombRate(struct track *tg) /* Free up recombRate items. */ { recombRateFreeList((struct recombRate**)&tg->items); } char *recombRateName(struct track *tg, void *item) /* Return name of recombRate track item. */ { struct recombRate *rr = item; static char buf[32]; switch (recombRateType) { case rroeDecodeAvg: case rroeMarshfieldAvg: case rroeGenethonAvg: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->decodeAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->decodeAvg); break; case rroeDecodeFemale: case rroeMarshfieldFemale: case rroeGenethonFemale: - sprintf(buf, "%3.1f cM/Mb (F)", rr->decodeAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (F)", rr->decodeAvg); break; case rroeDecodeMale: case rroeMarshfieldMale: case rroeGenethonMale: - sprintf(buf, "%3.1f cM/Mb (M)", rr->decodeAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (M)", rr->decodeAvg); break; default: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->decodeAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->decodeAvg); break; } return buf; } static int recombRateMin = 320; static int recombRateMax = 600; Color recombRateColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color for item in recombRate track item. */ { struct recombRate *rr = item; int rcr; int grayLevel; @@ -7132,34 +7468,34 @@ void freeRecombRateRat(struct track *tg) /* Free up recombRateRat items. */ { recombRateRatFreeList((struct recombRateRat**)&tg->items); } char *recombRateRatName(struct track *tg, void *item) /* Return name of recombRateRat track item. */ { struct recombRateRat *rr = item; static char buf[32]; switch (recombRateRatType) { case rrroeShrspAvg: case rrroeFhhAvg: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->shrspAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->shrspAvg); break; default: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->shrspAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->shrspAvg); break; } return buf; } Color recombRateRatColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color for item in recombRateRat track item. */ { struct recombRateRat *rr = item; int rcr; int grayLevel; rcr = (int)(rr->shrspAvg * 200); grayLevel = grayInRange(rcr, recombRateMin, recombRateMax); return shadesOfGray[grayLevel]; @@ -7210,34 +7546,34 @@ void freeRecombRateMouse(struct track *tg) /* Free up recombRateMouse items. */ { recombRateMouseFreeList((struct recombRateMouse**)&tg->items); } char *recombRateMouseName(struct track *tg, void *item) /* Return name of recombRateMouse track item. */ { struct recombRateMouse *rr = item; static char buf[32]; switch (recombRateMouseType) { case rrmoeWiAvg: case rrmoeMgdAvg: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->wiAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->wiAvg); break; default: - sprintf(buf, "%3.1f cM/Mb (Avg)", rr->wiAvg); + safef(buf, sizeof buf, "%3.1f cM/Mb (Avg)", rr->wiAvg); break; } return buf; } Color recombRateMouseColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color for item in recombRateMouse track item. */ { struct recombRateMouse *rr = item; int rcr; int grayLevel; rcr = (int)(rr->wiAvg * 200); grayLevel = grayInRange(rcr, recombRateMin, recombRateMax); return shadesOfGray[grayLevel]; @@ -7464,31 +7800,31 @@ void mrnaMethods(struct track *tg) /* Make track of mRNA methods. */ { tg->extraUiData = newMrnaUiData(tg->track, FALSE); } char *interProName(struct track *tg, void *item) { char condStr[255]; char *desc; struct bed *it = item; struct sqlConnection *conn; conn = hAllocConn(database); -sprintf(condStr, "interProId='%s' limit 1", it->name); +sqlSafef(condStr, sizeof condStr, "interProId='%s' limit 1", it->name); desc = sqlGetField("proteome", "interProXref", "description", condStr); hFreeConn(&conn); return(desc); } void interProMethods(struct track *tg) /* Make track of InterPro methods. */ { tg->itemName = interProName; } void estMethods(struct track *tg) /* Make track of EST methods - overrides color handler. */ { tg->drawItems = linkedFeaturesAverageDenseOrientEst; @@ -7657,30 +7993,31 @@ void interactionLeftLabels(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, int height, boolean withCenterLabels, MgFont *font, Color color, enum trackVisibility vis) { /* struct linkedFeatures *lf, *lfList = track->items; for (lf = lfList; lf != NULL; lf = lf->next) { if (tg->itemLabelColor != NULL) color = tg->itemLabelColor(track, lf, hvg); int itemHeight = tg->itemHeight(track, lf); hvGfxTextRight(hvg, xOff, y, width - 1, itemHeight, color, font, tg->itemName(tg, lf)); } + track->bigBedraLeftLabels = bigBedLeftLabels; */ } void interactionLoad(struct track *tg) { loadGappedBed(tg); } char *interactionName(struct track *tg, void *item) { struct linkedFeatures *lf = item; if (slCount(lf->components) == 2) return ""; char buffer[10 * 1024], *name = buffer; @@ -7774,31 +8111,31 @@ Color ncRnaColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color of ncRna track item. */ { char condStr[255]; char *rnaType; Color color = {MG_GRAY}; /* Set default to gray */ struct rgbColor hAcaColor = {0, 128, 0}; /* darker green, per request by Weber */ Color hColor; struct sqlConnection *conn; char *name; conn = hAllocConn(database); hColor = hvGfxFindColorIx(hvg, hAcaColor.r, hAcaColor.g, hAcaColor.b); name = tg->itemName(tg, item); -sprintf(condStr, "name='%s'", name); +sqlSafef(condStr, sizeof condStr, "name='%s'", name); rnaType = sqlGetField(database, "ncRna", "type", condStr); if (sameWord(rnaType, "miRNA")) color = MG_RED; if (sameWord(rnaType, "misc_RNA")) color = MG_BLACK; if (sameWord(rnaType, "snRNA")) color = MG_BLUE; if (sameWord(rnaType, "snoRNA")) color = MG_MAGENTA; if (sameWord(rnaType, "rRNA")) color = MG_CYAN; if (sameWord(rnaType, "scRNA")) color = MG_YELLOW; if (sameWord(rnaType, "Mt_tRNA")) color = MG_GREEN; if (sameWord(rnaType, "Mt_rRNA")) color = hColor; hFreeConn(&conn); return(color); } @@ -7811,31 +8148,31 @@ Color wgRnaColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color of wgRna track item. */ { char condStr[255]; char *rnaType; Color color = {MG_BLACK}; /* Set default to black. But, if we got black, something is wrong. */ Color hColor; struct rgbColor hAcaColor = {0, 128, 0}; /* darker green */ struct sqlConnection *conn; char *name; conn = hAllocConn(database); hColor = hvGfxFindColorIx(hvg, hAcaColor.r, hAcaColor.g, hAcaColor.b); name = tg->itemName(tg, item); -sprintf(condStr, "name='%s'", name); +sqlSafefFrag(condStr, sizeof condStr, "name='%s'", name); rnaType = sqlGetField(database, "wgRna", "type", condStr); if (sameWord(rnaType, "miRna")) color = MG_RED; if (sameWord(rnaType, "HAcaBox")) color = hColor; if (sameWord(rnaType, "CDBox")) color = MG_BLUE; if (sameWord(rnaType, "scaRna")) color = MG_MAGENTA; hFreeConn(&conn); return(color); } void wgRnaMethods(struct track *tg) /* Make track for wgRna. */ { tg->itemColor = wgRnaColor; } @@ -8644,31 +8981,31 @@ { bedLoadItem(tg, "gap", (ItemLoader)agpGapLoad); } void gapFree(struct track *tg) /* Free up gap items. */ { agpGapFreeList((struct agpGap**)&tg->items); } char *gapName(struct track *tg, void *item) /* Return name of gap track item. */ { static char buf[24]; struct agpGap *gap = item; -sprintf(buf, "%s %s", gap->type, gap->bridge); +safef(buf, sizeof buf, "%s %s", gap->type, gap->bridge); return buf; } static void gapDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw gap items. */ { struct agpGap *gap = item; int heightPer = tg->heightPer; int x1,x2,w; int halfSize = heightPer/2; x1 = round((double)((int)gap->chromStart-winStart)*scale) + xOff; x2 = round((double)((int)gap->chromEnd-winStart)*scale) + xOff; @@ -9082,32 +9419,31 @@ MgFont *font, Color color, enum trackVisibility vis) /* Draw triangle items. Relies mostly on bedDrawSimple, but does put * a horizontal box connecting items in full mode. */ { /* In dense mode try and draw golden background for promoter regions. */ if (vis == tvDense) { if (hTableExists(database, "esRegUpstreamRegion")) { int heightPer = tg->heightPer; Color gold = hvGfxFindColorIx(hvg, 250,190,60); int rowOffset; double scale = scaleForPixels(width); struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = hRangeQuery(conn, "esRegUpstreamRegion", - chromName, winStart, winEnd, - NULL, &rowOffset); + chromName, winStart, winEnd, NULL, &rowOffset); char **row; while ((row = sqlNextRow(sr)) != NULL) { int start, end; row += rowOffset; start = atoi(row[1]); end = atoi(row[2]); drawScaledBox(hvg, start, end, scale, xOff, yOff, heightPer, gold); } hFreeConn(&conn); } } bedDrawSimple(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis); } @@ -9185,96 +9521,97 @@ int ct = 0; for (subtrack = trackList; subtrack; subtrack = subtrack->next) if (isSubtrackVisible(subtrack)) ct++; return ct; } enum trackVisibility limitVisibility(struct track *tg) /* Return default visibility limited by number of items and * by parent visibility if part of a coposite track. * This also sets tg->height. */ { if (!tg->limitedVisSet) { tg->limitedVisSet = TRUE; // Prevents recursive loop! + + // optional setting to draw labels onto the feature boxes, not next to them + tg->drawLabelInBox = cartOrTdbBoolean(cart, tg->tdb, "labelOnFeature" , FALSE); if (trackShouldUseAjaxRetrieval(tg)) { tg->limitedVis = tg->visibility; tg->height = REMOTE_TRACK_HEIGHT; } else { enum trackVisibility vis = tg->visibility; int h; int maxHeight = maximumTrackHeight(tg); if (vis == tvHide) { tg->height = 0; tg->limitedVis = tvHide; return tvHide; } if (tg->subtracks != NULL) { struct track *subtrack; int subCnt = subtrackCount(tg->subtracks); - maxHeight = maxHeight * max(subCnt,1); // Without further restruction does this ever accomplish anything? + maxHeight = maxHeight * max(subCnt,1); //if (subCnt > 4) // maxHeight *= 2; // NOTE: Large composites should suffer an additional restriction. if (!tg->syncChildVisToSelf) { for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) limitVisibility(subtrack); } } while ((h = tg->totalHeight(tg, vis)) > maxHeight && vis != tvDense) { if (vis == tvFull && tg->canPack) vis = tvPack; else if (vis == tvPack) vis = tvSquish; else vis = tvDense; - //if (tg->visibility != vis) - // warn("DEMOTION: %s -> %s %s maxHeight:%d totHeight:%d", - // hStringFromTv(tg->visibility),hStringFromTv(vis),tg->track,maxHeight,tg->height); } tg->height = h; if (tg->limitedVis == tvHide) tg->limitedVis = vis; else tg->limitedVis = tvMin(vis,tg->limitedVis); } if (tg->syncChildVisToSelf) { struct track *subtrack; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { subtrack->visibility = tg->visibility; subtrack->limitedVis = tg->limitedVis; subtrack->limitedVisSet = tg->limitedVisSet; } } - else if (tdbIsComposite(tg->tdb)) // If a composite is restricted, it's children should be atleast as restricted. - { + else if (tdbIsComposite(tg->tdb)) // If a composite is restricted, + { // it's children should be atleast as restricted. struct track *subtrack; for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next) { subtrack->limitedVis = tvMin(subtrack->limitedVis, tg->limitedVis); - //subtrack->limitedVisSet = tg->limitedVisSet; // But don't prevent subtracks from being further restricted! + // But don't prevent subtracks from being further restricted! + //subtrack->limitedVisSet = tg->limitedVisSet; } } if (tg->height == 0 && tg->limitedVis != tvHide) tg->limitedVisSet = FALSE; // Items may not be loaded yet, so going to need to check again } return tg->limitedVis; } void compositeTrackVis(struct track *track) /* set visibilities of subtracks */ { struct track *subtrack; if (track->visibility == tvHide) @@ -9668,33 +10005,33 @@ } void loadPgSnp(struct track *tg) /* Load up pgSnp (personal genome SNP) type tracks */ { struct customTrack *ct = tg->customPt; char *table = tg->table; struct sqlConnection *conn; if (ct == NULL) conn = hAllocConn(database); else { conn = hAllocConn(CUSTOM_TRASH); table = ct->dbTableName; } -struct dyString *query = dyStringCreate("select * from %s where ", table); +struct dyString *query = sqlDyStringCreate("select * from %s where ", table); hAddBinToQuery(winStart, winEnd, query); -dyStringPrintf(query, "chrom = '%s' and chromStart < %d and chromEnd > %d", +sqlDyStringPrintf(query, "chrom = '%s' and chromStart < %d and chromEnd > %d", chromName, winEnd, winStart); tg->items = pgSnpLoadByQuery(conn, query->string); /* base coloring/display decision on count of items */ tg->customInt = slCount(tg->items); hFreeConn(&conn); } void pgSnpMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) /* create a special map box item with different * pop-up statusLine with allele counts */ { char *directUrl = trackDbSetting(tg->tdb, "directUrl"); boolean withHgsid = (trackDbSetting(tg->tdb, "hgsid") != NULL); @@ -9708,43 +10045,61 @@ chopByChar(nameCopy, '/', all, el->alleleCount); if (differentString(el->alleleFreq, "")) chopByChar(cntCopy, ',', freq, el->alleleCount); for (i=0; i < el->alleleCount; i++) { if (sameString(el->alleleFreq, "") || sameString(freq[i], "0")) freq[i] = "?"; dyStringPrintf(ds, "%s:%s ", all[i], freq[i]); } mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, tg->track, mapItemName, ds->string, directUrl, withHgsid, NULL); freeDyString(&ds); } +void pgSnpLeftLabels(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, int height, + boolean withCenterLabels, MgFont *font, Color color, + enum trackVisibility vis) +/* pgSnp draws its own left labels when it draws the item in pack or full mode. + * We don't want the default left labels when in full mode because they can overlap + * with the item-drawing labels, but we do still need dense mode left labels. */ +{ +if (tg->visibility == tvDense) + { + if (isCenterLabelIncluded(tg)) + yOff += mgFontLineHeight(font); + hvGfxTextRight(hvg, leftLabelX, yOff, leftLabelWidth-1, tg->lineHeight, + color, font, tg->shortLabel); + } +} + void pgSnpMethods (struct track *tg) /* Personal Genome SNPs: show two alleles with stacked color bars for base alleles and * (if available) allele counts in mouseover. */ { bedMethods(tg); tg->loadItems = loadPgSnp; tg->freeItems = freePgSnp; tg->totalHeight = pgSnpHeight; tg->itemName = pgSnpName; tg->drawItemAt = pgSnpDrawAt; tg->mapItem = pgSnpMapItem; tg->nextItemButtonable = TRUE; tg->nextPrevItem = linkedFeaturesLabelNextPrevItem; +tg->drawLeftLabels = pgSnpLeftLabels; } void loadBlatz(struct track *tg) { enum trackVisibility vis = tg->visibility; loadXenoPsl(tg); if (vis != tvDense) { lookupProteinNames(tg); } vis = limitVisibility(tg); } void loadBlast(struct track *tg) { @@ -10045,98 +10400,176 @@ void kiddEichlerMethods(struct track *tg) /* For variation data from Kidd,...,Eichler '08. */ { linkedFeaturesMethods(tg); tg->itemName = kiddEichlerItemName; } boolean dgvFilter(struct track *tg, void *item) /* For use with filterItems -- return TRUE if item's PubMed ID is in the list * specified by the user. */ { static struct slName *filterPmIds = NULL; struct linkedFeatures *lf = item; struct sqlConnection *conn = hAllocConn(database); char query[512]; -safef(query, sizeof(query), "select pubmedId from %s where name = '%s'", +sqlSafef(query, sizeof(query), "select pubmedId from %s where name = '%s'", tg->tdb->table, lf->name); char buf[32]; char *pmId = sqlQuickQuery(conn, query, buf, sizeof(buf)); hFreeConn(&conn); if (filterPmIds == NULL) { char cartVarName[256]; safef (cartVarName, sizeof(cartVarName), "hgt_%s_filterPmId", tg->tdb->track); filterPmIds = cartOptionalSlNameList(cart, cartVarName); } return slNameInList(filterPmIds, pmId); } void loadDgv(struct track *tg) /* Load Database of Genomic Variants items, filtering by pubmedId if specified. */ { loadBed9(tg); char cartVarName[256]; safef (cartVarName, sizeof(cartVarName), "hgt_%s_filterType", tg->tdb->track); char *incOrExc = cartUsualString(cart, cartVarName, NULL); if (isNotEmpty(incOrExc)) filterItems(tg, dgvFilter, incOrExc); } - -void dgvMethods(struct track *tg) -/* Database of Genomic Variants. */ + +void dgvMethods(struct track *tg) +/* Database of Genomic Variants. */ +{ +linkedFeaturesMethods(tg); +tg->loadItems = loadDgv; +} + +void loadGenePred(struct track *tg) +/* Convert gene pred in window to linked feature. */ +{ +tg->items = lfFromGenePredInRange(tg, tg->table, chromName, winStart, winEnd); +/* filter items on selected criteria if filter is available */ +filterItems(tg, genePredClassFilter, "include"); +} + +static char *ensGeneName(struct track *tg, void *item) +{ +static char cat[128]; +struct linkedFeatures *lf = item; +if (lf->extra != NULL) + { + safef(cat, sizeof(cat), "%s", (char *)lf->extra); + return cat; + } +else + return lf->name; +} + +static void ensGeneAssignConfiguredName(struct track *tg) +/* Set name on genePred in "extra" field to gene symbol, ENSG id, or ENST id, + * depending, on UI on all items in track */ +{ +char *geneLabel = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, "label","accession"); +boolean otherGeneName = sameString(geneLabel, "gene symbol"); +boolean useGeneName = sameString(geneLabel, "ENSG* identifier"); +boolean useAcc = sameString(geneLabel, "ENST* identifier"); +struct sqlConnection *conn = NULL; +if (otherGeneName) + conn = hAllocConn(database); + +struct linkedFeatures *lf; +for (lf = tg->items; lf != NULL; lf = lf->next) + { + struct dyString *name = dyStringNew(SMALLDYBUF); + if (otherGeneName) + { + char buf[256]; + char query[256]; + sqlSafef(query, sizeof(query), + "select value from ensemblToGeneName where name = \"%s\"", lf->name); + char *ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); + if (isNotEmpty(ret)) + dyStringAppend(name, ret); + else + dyStringAppend(name, lf->name); + } + else if (useGeneName) { -linkedFeaturesMethods(tg); -tg->loadItems = loadDgv; + if (isNotEmpty((char*)lf->extra)) + dyStringAppend(name, lf->extra); + else + dyStringAppend(name, lf->name); + } + else if (useAcc) + { + dyStringAppend(name, lf->name); + } + else + lf->extra = NULL; + if (dyStringLen(name)) + lf->extra = dyStringCannibalize(&name); + dyStringFree(&name); + } +if (otherGeneName) + hFreeConn(&conn); } -void loadGenePred(struct track *tg) +static void loadGenePredEnsGene(struct track *tg) /* Convert gene pred in window to linked feature. */ { -tg->items = lfFromGenePredInRange(tg, tg->table, chromName, winStart, winEnd); -/* filter items on selected criteria if filter is available */ -filterItems(tg, genePredClassFilter, "include"); +loadGenePredWithName2(tg); +ensGeneAssignConfiguredName(tg); +tg->itemName = ensGeneName; } -void loadGenePredWithConfiguredName(struct track *tg) -/* Convert gene pred info in window to linked feature. Include name - * in "extra" field (gene name, accession, or both, depending on UI) */ +void genePredAssignConfiguredName(struct track *tg) +/* Set name on genePred in "extra" field to gene name, accession, or both, + * depending, on UI on all items in track */ { -char *geneLabel; -boolean useGeneName, useAcc; -struct linkedFeatures *lf; - -geneLabel = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, "label","gene"); -useGeneName = sameString(geneLabel, "gene") || sameString(geneLabel, "name") || sameString(geneLabel, "both"); -useAcc = sameString(geneLabel, "accession") || sameString(geneLabel, "both"); +char *geneLabel = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, "label","gene"); +boolean useGeneName = sameString(geneLabel, "gene") + || sameString(geneLabel, "name") + || sameString(geneLabel, "both"); +boolean useAcc = sameString(geneLabel, "accession") || sameString(geneLabel, "both"); -loadGenePredWithName2(tg); +struct linkedFeatures *lf; for (lf = tg->items; lf != NULL; lf = lf->next) { struct dyString *name = dyStringNew(SMALLDYBUF); if (useGeneName && !isEmpty((char*)lf->extra)) { dyStringAppend(name, lf->extra); if (useAcc) dyStringAppendC(name, '/'); } if (useAcc) dyStringAppend(name, lf->name); + if (dyStringLen(name)) lf->extra = dyStringCannibalize(&name); + dyStringFree(&name); } } +void loadGenePredWithConfiguredName(struct track *tg) +/* Convert gene pred info in window to linked feature. Include name + * in "extra" field (gene name, accession, or both, depending on UI) */ +{ +loadGenePredWithName2(tg); +genePredAssignConfiguredName(tg); +} + Color genePredItemAttrColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw a genePred in based on looking it up in a itemAttr * table. */ { struct linkedFeatures *lf = item; if (lf->itemAttr != NULL) return hvGfxFindColorIx(hvg, lf->itemAttr->colorR, lf->itemAttr->colorG, lf->itemAttr->colorB); else return tg->ixColor; } Color genePredItemClassColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw a genePred based on looking up the gene class */ /* in an itemClass table. */ { @@ -10159,31 +10592,31 @@ int color = tg->ixColor; /* default color in trackDb */ int size = 3; char *rgbVals[5]; char *sep = ","; if (geneClasses == NULL) errAbort( "Track %s missing required trackDb setting: geneClasses", tg->track); if (geneClasses) { gClassesClone = cloneString(geneClasses); classCt = chopLine(gClassesClone, classes); } if (hTableExists(database, classTable)) { - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select %s from %s where %s = \"%s\"", classCol, classTable, nameCol, lf->name); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { /* scan through groups to find a match */ for (class = 0; class < classCt; class++) { if (sameString(classes[class], row[0])) /* get color from trackDb settings hash */ { found = TRUE; safef(gClass, sizeof(gClass), "%s%s", GENEPRED_CLASS_PREFIX, classes[class]); colorString = trackDbSetting(tg->tdb, gClass); if (!colorString) found = FALSE; @@ -10213,77 +10646,30 @@ void drawColorMethods(struct track *tg) /* Fill in color track items based on chrom */ { char *optionStr ; optionStr = cartUsualStringClosestToHome(cart, tg->tdb,FALSE,"color", "off"); tg->mapItemName = lfMapNameFromExtra; if( sameString( optionStr, "on" )) /*use chromosome coloring*/ tg->itemColor = lfChromColor; else tg->itemColor = NULL; linkedFeaturesMethods(tg); tg->loadItems = loadGenePred; } -Color gencodeIntronColorItem(struct track *tg, void *item, struct hvGfx *hvg) -/* Return color of ENCODE gencode intron track item. - * Use recommended color palette pantone colors (level 4) for red, green, blue*/ -{ -struct gencodeIntron *intron = (struct gencodeIntron *)item; - -if (sameString(intron->status, "not_tested")) - return hvGfxFindColorIx(hvg, 214,214,216); /* light grey */ -if (sameString(intron->status, "RT_negative")) - return hvGfxFindColorIx(hvg, 145,51,56); /* red */ -if (sameString(intron->status, "RT_positive") || - sameString(intron->status, "RACE_validated")) - return hvGfxFindColorIx(hvg, 61,142,51); /* green */ -if (sameString(intron->status, "RT_wrong_junction")) - return getOrangeColor(hvg); /* orange */ -if (sameString(intron->status, "RT_submitted")) - return hvGfxFindColorIx(hvg, 102,109,112); /* grey */ -return hvGfxFindColorIx(hvg, 214,214,216); /* light grey */ -} - -static void gencodeIntronLoadItems(struct track *tg) -/* Load up track items. */ -{ -bedLoadItem(tg, tg->table, (ItemLoader)gencodeIntronLoad); -} - -static void gencodeIntronMethods(struct track *tg) -/* Load up custom methods for ENCODE Gencode intron validation track */ -{ -tg->loadItems = gencodeIntronLoadItems; -tg->itemColor = gencodeIntronColorItem; -} - -static void gencodeGeneMethods(struct track *tg) -/* Load up custom methods for ENCODE Gencode gene track */ -{ -tg->loadItems = loadGenePredWithConfiguredName; -tg->itemName = gencodeGeneName; -} - -static void gencodeRaceFragsMethods(struct track *tg) -/* Load up custom methods for ENCODE Gencode RACEfrags track */ -{ -tg->loadItems = loadGenePred; -tg->subType = lfNoIntronLines; -} - void loadDless(struct track *tg) /* Load dless items */ { struct sqlConnection *conn = hAllocConn(database); struct dless *dless, *list = NULL; struct sqlResult *sr; char **row; int rowOffset; sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset); while ((row = sqlNextRow(sr)) != NULL) { dless = dlessLoad(row+rowOffset); slAddHead(&list, dless); @@ -10376,43 +10762,41 @@ } void vegaMethods(struct track *tg) /* Special handling for vegaGene/vegaPseudoGene items. */ { tg->loadItems = loadGenePredWithConfiguredName; tg->itemColor = vegaColor; tg->itemName = vegaGeneName; } Color gvColorByCount(struct track *tg, void *item, struct hvGfx *hvg) /* color items by whether they are single position or multiple */ { struct gvPos *el = item; struct sqlConnection *conn = hAllocConn(database); -char *escId = NULL; +char *id = NULL; char *multColor = NULL, *singleColor = NULL; int num = 0; char query[256]; if (el->id != NULL) - escId = sqlEscapeString(el->id); + id = el->id; else - escId = sqlEscapeString(el->name); -safef(query, sizeof(query), "select count(*) from gvPos where name = '%s'", - escId); + id = el->name; +sqlSafef(query, sizeof(query), "select count(*) from gvPos where name = '%s'", id); num = sqlQuickNum(conn, query); hFreeConn(&conn); -freeMem(escId); singleColor = cartUsualString(cart, "gvColorCountSingle", "blue"); multColor = cartUsualString(cart, "gvColorCountMult", "green"); if (num == 1) { if (sameString(singleColor, "red")) return hvGfxFindColorIx(hvg, 221, 0, 0); /* dark red */ else if (sameString(singleColor, "orange")) return hvGfxFindColorIx(hvg, 255, 153, 0); else if (sameString(singleColor, "green")) return hvGfxFindColorIx(hvg, 0, 153, 0); /* dark green */ else if (sameString(singleColor, "gray")) return MG_GRAY; else if (sameString(singleColor, "purple")) return hvGfxFindColorIx(hvg, 204, 0, 255); else if (sameString(singleColor, "blue")) @@ -10439,102 +10823,100 @@ else if (sameString(multColor, "brown")) return hvGfxFindColorIx(hvg, 100, 50, 0); /* brown */ else return MG_BLACK; } else return MG_BLACK; } Color gvColorByDisease(struct track *tg, void *item, struct hvGfx *hvg) /* color items by whether they are known or likely to cause disease */ { struct gvPos *el = item; struct gvAttr *attr = NULL; struct sqlConnection *conn = hAllocConn(database); -char *escId = NULL; +char *id = NULL; char *useColor = NULL; int index = -1; char query[256]; if (el->id != NULL) - escId = sqlEscapeString(el->id); + id = el->id; else - escId = sqlEscapeString(el->name); -safef(query, sizeof(query), "select * from hgFixed.gvAttr where id = '%s' and attrType = 'disease'", escId); + id = el->name; +sqlSafef(query, sizeof(query), "select * from hgFixed.gvAttr where id = '%s' and attrType = 'disease'", id); attr = gvAttrLoadByQuery(conn, query); if (attr == NULL) { AllocVar(attr); attr->attrVal = cloneString("NULL"); attr->id = NULL; /* so free will work */ attr->attrType = NULL; } index = stringArrayIx(attr->attrVal, gvColorDAAttrVal, gvColorDASize); if (index < 0 || index >= gvColorDASize) { hFreeConn(&conn); return MG_BLACK; } useColor = cartUsualString(cart, gvColorDAStrings[index], gvColorDADefault[index]); gvAttrFreeList(&attr); hFreeConn(&conn); -freeMem(escId); if (sameString(useColor, "red")) return hvGfxFindColorIx(hvg, 221, 0, 0); /* dark red */ else if (sameString(useColor, "orange")) return hvGfxFindColorIx(hvg, 255, 153, 0); else if (sameString(useColor, "green")) return hvGfxFindColorIx(hvg, 0, 153, 0); /* dark green */ else if (sameString(useColor, "gray")) return MG_GRAY; else if (sameString(useColor, "purple")) return hvGfxFindColorIx(hvg, 204, 0, 255); else if (sameString(useColor, "blue")) return MG_BLUE; else if (sameString(useColor, "brown")) return hvGfxFindColorIx(hvg, 100, 50, 0); /* brown */ else return MG_BLACK; } Color gvColorByType(struct track *tg, void *item, struct hvGfx *hvg) /* color items by type */ { struct gvPos *el = item; struct gv *details = NULL; struct sqlConnection *conn = hAllocConn(database); char *typeColor = NULL; int index = 5; -char *escId = NULL; +char *id = NULL; char query[256]; if (el->id != NULL) - escId = sqlEscapeString(el->id); + id = el->id; else - escId = sqlEscapeString(el->name); + id = el->name; -safef(query, sizeof(query), "select * from hgFixed.gv where id = '%s'", escId); +sqlSafef(query, sizeof(query), "select * from hgFixed.gv where id = '%s'", id); details = gvLoadByQuery(conn, query); index = stringArrayIx(details->baseChangeType, gvColorTypeBaseChangeType, gvColorTypeSize); if (index < 0 || index >= gvColorTypeSize) { hFreeConn(&conn); return MG_BLACK; } typeColor = cartUsualString(cart, gvColorTypeStrings[index], gvColorTypeDefault[index]); gvFreeList(&details); hFreeConn(&conn); -freeMem(escId); if (sameString(typeColor, "purple")) return hvGfxFindColorIx(hvg, 204, 0, 255); else if (sameString(typeColor, "green")) return hvGfxFindColorIx(hvg, 0, 153, 0); /* dark green */ else if (sameString(typeColor, "orange")) return hvGfxFindColorIx(hvg, 255, 153, 0); else if (sameString(typeColor, "blue")) return MG_BLUE; else if (sameString(typeColor, "brown")) return hvGfxFindColorIx(hvg, 100, 50, 0); /* brown */ else if (sameString(typeColor, "gray")) return MG_GRAY; else if (sameString(typeColor, "red")) return hvGfxFindColorIx(hvg, 221, 0, 0); /* dark red */ else @@ -10550,51 +10932,50 @@ return gvColorByType(tg, item, hvg); else if (choice != NULL && sameString(choice, "count")) return gvColorByCount(tg, item, hvg); else if (choice != NULL && sameString(choice, "disease")) return gvColorByDisease(tg, item, hvg); else return gvColorByType(tg, item, hvg); } Color oregannoColor(struct track *tg, void *item, struct hvGfx *hvg) /* color items by type for ORegAnno track */ { struct oreganno *el = item; struct oregannoAttr *details = NULL; struct sqlConnection *conn = hAllocConn(database); -char *escId = NULL; +char *id = NULL; char query[256]; Color itemColor = MG_BLACK; if (el->id != NULL) - escId = sqlEscapeString(el->id); + id = el->id; else - escId = sqlEscapeString(el->name); + id = el->name; -safef(query, sizeof(query), "select * from oregannoAttr where attribute = 'type' and id = '%s'", escId); +sqlSafef(query, sizeof(query), "select * from oregannoAttr where attribute = 'type' and id = '%s'", id); details = oregannoAttrLoadByQuery(conn, query); /* ORegAnno colors 666600 (Dark Green), CCCC66 (Tan), CC0033 (Red), CCFF99 (Background Green) */ if (sameString(details->attrVal, "REGULATORY POLYMORPHISM")) itemColor = hvGfxFindColorIx(hvg, 204, 0, 51); /* red */ else if (sameString(details->attrVal, "TRANSCRIPTION FACTOR BINDING SITE")) itemColor = hvGfxFindColorIx(hvg, 165, 165, 65); /* tan, darkened some */ else if (sameString(details->attrVal, "REGULATORY REGION")) itemColor = hvGfxFindColorIx(hvg, 102, 102, 0); /* dark green */ oregannoAttrFreeList(&details); hFreeConn(&conn); -freeMem(escId); return itemColor; } Color omiciaColor(struct track *tg, void *item, struct hvGfx *hvg) /* color by confidence score */ { struct bed *el = item; if (sameString(tg->table, "omiciaHand")) return hvGfxFindColorIx(hvg, 0, 0, 0); else if (el->score < 200) return MG_BLACK; else if (el->score < 600) return hvGfxFindColorIx(hvg, 230, 130, 0); /* orange */ else return MG_GREEN; @@ -10866,92 +11247,92 @@ static char *omimGene2DisorderList(char *name) /* Return list of disorders associated with a OMIM entry. Do not free result! */ { static struct dyString *dy = NULL; struct sqlConnection *conn; char query[256]; if (dy == NULL) dy = dyStringNew(0); dyStringClear(dy); // get gene symbol(s) first conn = hAllocConn(database); -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select geneSymbol from omimGeneMap where omimId =%s", name); char buf[256]; char *ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); if (isNotEmpty(ret)) dyStringAppend(dy, ret); -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select distinct description from omimPhenotype, omimGene2 where name='%s' and name=cast(omimId as char) order by description", name); char *disorders = collapseRowsFromQuery(query, "; ", 20); if (isNotEmpty(disorders)) { dyStringAppend(dy, "; disorder(s): "); dyStringAppend(dy, disorders); } hFreeConn(&conn); return(dy->string); } #include "omim.h" boolean isOmimOtherClass(char *omimId) /* check if this omimId belongs to the "Others" phenotype class */ /* NOTE: The definition of Others class is kind of tricky. The Other class is defined as: 1. does not have class 1 or 2 or 3, or 4; some may have class '-1'. 2. for an entry of omimId that the omimPhenotype table does not even have a row with omimId */ { boolean result; char answer[255]; struct sqlConnection *conn = hAllocConn(database); char query[256]; -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select %s from omimPhenotype where omimId =%s and (%s=1 or %s=2 or %s=3 or %s=4)", - omimPhenotypeClassColName, omimId, omimPhenotypeClassColName, omimPhenotypeClassColName, omimPhenotypeClassColName, - omimPhenotypeClassColName); + omimPhenotypeClassColName, omimId, omimPhenotypeClassColName, omimPhenotypeClassColName, + omimPhenotypeClassColName, omimPhenotypeClassColName); char *ret = sqlQuickQuery(conn, query, answer, sizeof(answer)); if (ret == NULL) { result = TRUE; } else { result = FALSE; } hFreeConn(&conn); return(result); } int hasOmimPhenotypeClass(char *omimId, int targetClass) /* Look up phenotypeClass for omimId, for filtering items. Don't free result! */ { int result; char answer[255]; struct sqlConnection *conn = hAllocConn(database); char query[256]; -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select %s from omimPhenotype where omimId =%s and %s=%d", omimPhenotypeClassColName,omimId,omimPhenotypeClassColName,targetClass); char *ret = sqlQuickQuery(conn, query, answer, sizeof(answer)); if (ret == NULL) { if (targetClass == -1) { result = -1; } else { result = 0; } } @@ -11086,31 +11467,31 @@ lighter.b = (6*normal->b + 4*255) / 10; lightest.r = (1*normal->r + 2*255) / 3; lightest.g = (1*normal->g + 2*255) / 3; lightest.b = (1*normal->b + 2*255) / 3; struct sqlConnection *conn = hAllocConn(database); class1Clr = hvGfxFindColorIx(hvg, lightest.r, lightest.g, lightest.b); class2Clr = hvGfxFindColorIx(hvg, lighter.r, lighter.g, lighter.b); class3Clr = hvGfxFindColorIx(hvg, normal->r, normal->g, normal->b); class4Clr = hvGfxFindColorIx(hvg, 105,50,155); classOtherClr = hvGfxFindColorIx(hvg, 190, 190, 190); // light gray -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select omimId, %s from omimPhenotype where omimId=%s order by %s desc", omimPhenotypeClassColName, el->name, omimPhenotypeClassColName); sr = sqlMustGetResult(conn, query); row = sqlNextRow(sr); hFreeConn(&conn); if (row == NULL) { // set to gray if this entry does not have any disorder info sqlFreeResult(&sr); return classOtherClr; } else @@ -11195,115 +11576,115 @@ if (omimId != NULL) { dyStringAppend(name, omimId); } labelStarted = TRUE; } if (useGeneSymbol) { if (labelStarted) dyStringAppendC(name, '/'); else labelStarted = TRUE; // get appoved gene symbol from omim2gene table first, if not available then get it from omimGeneMap table. char query[256]; - safef(query, sizeof(query), "select approvedGeneSymbol from omim2gene where omimId = %s", el->name); + sqlSafef(query, sizeof(query), "select approvedGeneSymbol from omim2gene where omimId = %s", el->name); geneSymbol = sqlQuickString(conn, query); if (geneSymbol && differentString(geneSymbol, "-")) dyStringAppend(name, geneSymbol); else { char *chp; - safef(query, sizeof(query), "select geneSymbol from omimGeneMap where omimId = %s", el->name); + sqlSafef(query, sizeof(query), "select geneSymbol from omimGeneMap where omimId = %s", el->name); geneSymbol = sqlQuickString(conn, query); if (geneSymbol && differentString(geneSymbol, "0")) { // pick the first one, if multiple gene symbols exist chp = strstr(geneSymbol, ","); if (chp != NULL) *chp = '\0'; dyStringAppend(name, geneSymbol); } } } hFreeConn(&conn); return(name->string); } static char *cosmicTissueList(char *name) /* Return list of tumor tissues associated with a COSMIC entry. Do not free result! */ { static struct dyString *dy = NULL; struct sqlConnection *conn = hAllocConn(database); if (dy == NULL) dy = dyStringNew(0); dyStringClear(dy); char query[256]; -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select concat(gene_name,' ',mut_syntax_aa) from cosmicRaw where cosmic_mutation_id ='%s'", name); char buf[256]; char *ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); if (isNotEmpty(ret)) dyStringAppend(dy, ret); -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select sum(mutated_samples) from cosmicRaw where cosmic_mutation_id='%s'", name); ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); if (isNotEmpty(ret)) { dyStringAppend(dy, " "); dyStringAppend(dy, ret); } -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select sum(examined_samples) from cosmicRaw where cosmic_mutation_id='%s'", name); ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); { dyStringAppend(dy, "/"); dyStringAppend(dy, ret); } -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select sum(mutated_samples)*100/sum(examined_samples) from cosmicRaw where cosmic_mutation_id='%s'", name); ret = sqlQuickQuery(conn, query, buf, sizeof(buf)); char *chp = strstr(ret, "."); if (isNotEmpty(ret)) { // cut off digits after .xxx if ((chp != NULL) && (strlen(chp) > 3)) { chp++; chp++; chp++; chp++; *chp = '\0'; } dyStringAppend(dy, " ("); dyStringAppend(dy, ret); dyStringAppend(dy, "\%)"); } -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select tumour_site from cosmicRaw where cosmic_mutation_id ='%s' order by tumour_site", name); char *disorders = collapseRowsFromQuery(query, ",", 4); if (isNotEmpty(disorders)) { dyStringAppend(dy, " "); dyStringAppend(dy, disorders); } hFreeConn(&conn); return(dy->string); } static void cosmicLoad(struct track *tg) /* Load COSMIC items, storing long label from cosmicTissueList */ { bedPlusLabelLoad(tg, cosmicTissueList); @@ -11330,31 +11711,31 @@ tg->nextPrevExon = simpleBedNextPrevEdge; } static char *omimAvSnpAaReplacement(char *name) /* Return replacement string associated with a OMIM AV (Allelic Variant) entry */ { static char omimAvSnpBuffer[256]; struct sqlConnection *conn; char query[256]; struct sqlResult *sr; char **row; omimAvSnpBuffer[0] = '\0'; conn = hAllocConn(database); -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select replStr, dbSnpId, description from omimAvRepl where avId='%s'", name); sr = sqlMustGetResult(conn, query); row = sqlNextRow(sr); if (row != NULL) { safef(omimAvSnpBuffer, sizeof(omimAvSnpBuffer), "%s, %s: %s", row[0], row[1], row[2]); } hFreeConn(&conn); sqlFreeResult(&sr); return(omimAvSnpBuffer); } static void omimAvSnpLoad(struct track *tg) @@ -11371,31 +11752,31 @@ tg->mapItem = bedPlusLabelMapItem; tg->nextPrevExon = simpleBedNextPrevEdge; } static char *omimLocationDescription(char *name) /* Return description of an OMIM entry */ { static char omimLocationBuffer[512]; struct sqlConnection *conn; char query[256]; omimLocationBuffer[0] = '\0'; conn = hAllocConn(database); -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select concat(title1, ' ', title2) from omimGeneMap where omimId=%s", name); (void)sqlQuickQuery(conn, query, omimLocationBuffer, sizeof(omimLocationBuffer)); hFreeConn(&conn); return(omimLocationBuffer); } Color omimLocationColor(struct track *tg, void *item, struct hvGfx *hvg) /* set the color for omimLocation track items */ { struct bed *el = item; char *omimId; char *phenClass; char query[256]; struct sqlResult *sr; char **row; @@ -11424,31 +11805,31 @@ lighter.g = (6*normal->g + 4*255) / 10; lighter.b = (6*normal->b + 4*255) / 10; lightest.r = (1*normal->r + 2*255) / 3; lightest.g = (1*normal->g + 2*255) / 3; lightest.b = (1*normal->b + 2*255) / 3; class1Clr = hvGfxFindColorIx(hvg, lightest.r, lightest.g, lightest.b); class2Clr = hvGfxFindColorIx(hvg, lighter.r, lighter.g, lighter.b); class3Clr = hvGfxFindColorIx(hvg, normal->r, normal->g, normal->b); class4Clr = hvGfxFindColorIx(hvg, 105,50,155); classOtherClr = hvGfxFindColorIx(hvg, 190, 190, 190); // light gray struct sqlConnection *conn = hAllocConn(database); -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select omimId, %s from omimPhenotype where omimId=%s", omimPhenotypeClassColName, el->name); sr = sqlMustGetResult(conn, query); row = sqlNextRow(sr); hFreeConn(&conn); if (row == NULL) { // set to gray if this entry does not have any disorder info sqlFreeResult(&sr); return classOtherClr; } else { omimId = row[0]; @@ -11518,100 +11899,102 @@ char query[256]; struct sqlConnection *conn = hAllocConn(database); char *geneLabel = NULL; char *omimGeneLabel = cartUsualString(cart, "omimGene.label", "OMIM ID"); if (sameWord(omimGeneLabel, "OMIM ID")) { geneLabel = el->name; } else { if (sameWord(omimGeneLabel, "UCSC gene symbol")) { /* get the gene symbol of the exact KG that matches not only ID but also genomic position */ - safef(query, sizeof(query), - "select x.geneSymbol from kgXref x, omimToKnownCanonical c, knownGene k, omimGene o where c.omimId='%s' and c.kgId=x.kgId and k.name=x.kgId and o.name=c.omimId and o.chrom=k.chrom and k.txStart=%d and k.txEnd=%d", + sqlSafef(query, sizeof(query), + "select x.geneSymbol from kgXref x, omimToKnownCanonical c, knownGene k, omimGene o" + " where c.omimId='%s' and c.kgId=x.kgId and k.name=x.kgId and o.name=c.omimId" + " and o.chrom=k.chrom and k.txStart=%d and k.txEnd=%d", el->name, el->chromStart, el->chromEnd); geneLabel = sqlQuickString(conn, query); } else { - safef(query, sizeof(query), + sqlSafef(query, sizeof(query), "select geneSymbol from omimGeneMap where omimId='%s'", el->name); geneLabel = sqlQuickString(conn, query); } if (geneLabel == NULL) { geneLabel = el->name; } } hFreeConn(&conn); return(cloneString(geneLabel)); } Color omimGeneColor(struct track *tg, void *item, struct hvGfx *hvg) /* set the color for omimGene track items */ { struct bed *el = item; char *geneSymbols; char query[256]; struct sqlConnection *conn = hAllocConn(database); /* set the color to red if the entry is listed in morbidmap */ -safef(query, sizeof(query), "select geneSymbols from omimMorbidMap where omimId=%s", el->name); +sqlSafef(query, sizeof(query), "select geneSymbols from omimMorbidMap where omimId=%s", el->name); geneSymbols = sqlQuickString(conn, query); hFreeConn(&conn); if (geneSymbols != NULL) { return hvGfxFindColorIx(hvg, 255, 0, 0); } else { return hvGfxFindColorIx(hvg, 0, 0, 200); } } Color omimGeneColor2(struct track *tg, void *item, struct hvGfx *hvg) /* set the color for omimGene track items */ { struct bed *el = item; char *geneSymbols; char query[256]; struct sqlConnection *conn = hAllocConn(database); /* set the color to red if the entry is listed in morbidmap */ -safef(query, sizeof(query), "select geneSymbols from omimMorbidMap where omimId=%s", el->name); +sqlSafef(query, sizeof(query), "select geneSymbols from omimMorbidMap where omimId=%s", el->name); geneSymbols = sqlQuickString(conn, query); hFreeConn(&conn); if (geneSymbols != NULL) { return hvGfxFindColorIx(hvg, 255, 0, 0); } else { return hvGfxFindColorIx(hvg, 0, 0, 200); } } static char *omimGeneDiseaseList(char *name) /* Return list of diseases associated with a OMIM entry */ { char query[256]; -safef(query,sizeof(query), +sqlSafef(query,sizeof(query), "select distinct description from omimMorbidMap, omimGene " "where name='%s' and name=cast(omimId as char) order by description", name); return collapseRowsFromQuery(query, "; ", 20); } static void omimGeneLoad(struct track *tg) /* Load OMIM Genes, storing long label from omimGeneDiseaseList. */ { bedPlusLabelLoad(tg, omimGeneDiseaseList); } void omimGeneMethods (struct track *tg) /* Methods for original OMIM Genes track. */ { tg->loadItems = omimGeneLoad; @@ -11801,31 +12184,31 @@ } void loadVariome(struct track *tg) /* Load the items from the variome table (based on wikiTrackLoadItems) */ { struct bed *bed; struct sqlConnection *conn = wikiConnect(); struct sqlResult *sr; char **row; int rowOffset; char where[256]; struct linkedFeatures *lfList = NULL, *lf; int scoreMin = 0; int scoreMax = 99999; -safef(where, ArraySize(where), "db='%s'", database); +sqlSafefFrag(where, ArraySize(where), "db='%s'", database); sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, where, &rowOffset); while ((row = sqlNextRow(sr)) != NULL) { struct variome *item = variomeLoad(row); AllocVar(bed); bed->chrom = cloneString(item->chrom); bed->chromStart = item->chromStart; bed->chromEnd = item->chromEnd; bed->name = cloneString(item->name); bed->score = item->score; safecpy(bed->strand, sizeof(bed->strand), item->strand); bed->thickStart = item->chromStart; bed->thickEnd = item->chromEnd; bed->itemRgb = bedParseRgb(item->color); @@ -11909,32 +12292,32 @@ linkedFeaturesMethods(tg); AllocVar(tdb); tg->track = "variome"; tg->table = "variome"; tg->canPack = TRUE; tg->visibility = tvHide; tg->hasUi = TRUE; tg->shortLabel = cloneString("New variants"); safef(longLabel, sizeof(longLabel), "New variant submission for microattribtution review"); tg->longLabel = longLabel; tg->loadItems = loadVariome; tg->itemName = linkedFeaturesName; tg->mapItemName = variomeMapItemName; tg->mapItem = variomeMapItem; - tg->priority = 500.4; - tg->defaultPriority = 500.4; + tg->priority = WIKI_TRACK_PRIORITY; + tg->defaultPriority = WIKI_TRACK_PRIORITY; tg->groupName = cloneString("varRep"); tg->defaultGroupName = cloneString("varRep"); tg->exonArrows = FALSE; tg->nextItemButtonable = TRUE; tdb->track = cloneString(tg->track); tdb->table = cloneString(tg->table); tdb->shortLabel = cloneString(tg->shortLabel); tdb->longLabel = cloneString(tg->longLabel); tdb->useScore = 1; tdb->grp = cloneString(tg->groupName); tdb->priority = tg->priority; trackDbPolish(tdb); tg->tdb = tdb; slAddHead(pGroupList, tg); @@ -11965,31 +12348,31 @@ int ii; char query[256]; struct sqlResult *sr; long long offset = 0; char *fileName = NULL; struct sqlConnection *conn; char **row; FILE *f; unsigned short *mem, *p; boolean complementBases = cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE); if (!zoomedToBaseLevel) return; conn = hAllocConn(database); -safef(query, sizeof(query), +sqlSafef(query, sizeof(query), "select offset,fileName from %s where chrom = '%s'", tg->table,chromName); sr = sqlGetResult(conn, query); if ((row = sqlNextRow(sr)) != NULL) { offset = sqlLongLong(row[0]); fileName = cloneString(row[1]); } sqlFreeResult(&sr); hFreeConn(&conn); if (offset == 0) return; /* we should have found a non-zero offset */ AllocVar(motif); @@ -12035,32 +12418,31 @@ tg->items = motif; } int logoHeight(struct track *tg, enum trackVisibility vis) /* set up size of sequence logo */ { if (tg->items == NULL) tg->height = tg->lineHeight; else tg->height = 52; return tg->height; } -void logoMethods(struct track *track, struct trackDb *tdb, - int argc, char *argv[]) +void logoMethods(struct track *track, struct trackDb *tdb, int argc, char *argv[]) /* Load up logo type methods. */ { track->loadItems = logoLoad; track->drawLeftLabels = logoLeftLabels; track->drawItems = logoDrawSimple; track->totalHeight = logoHeight; track->mapsSelf = TRUE; } #endif /* GBROWSE */ static void remoteDrawItems(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) { @@ -12128,398 +12510,30 @@ // end stuff copied from hgTracks.c enum trackVisibility trackVis = track->tdb->visibility; if (s != NULL) trackVis = hTvFromString(s); if (trackVis != tvHide) { track->visibility = tvDense; track->limitedVis = tvDense; track->limitedVisSet = TRUE; } track->nextItemButtonable = track->nextExonButtonable = FALSE; track->nextPrevItem = NULL; track->nextPrevExon = NULL; } -char* pubsArticleTable(struct track *tg) -/* return the name of the pubs articleTable, either - * the value from the trackDb statement 'articleTable' - * or the default value: <trackName>Article */ -{ -char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable"); -if (isEmpty(articleTable)) - { - char buf[256]; - safef(buf, sizeof(buf), "%sArticle", tg->track); - articleTable = cloneString(buf); - } -return articleTable; -} - -static char *makeMysqlMatchStr(char *str) -{ -// return a string with all words prefixed with a '+' to force a boolean AND query; -// we also strip leading/trailing spaces. -char *matchStr = needMem(strlen(str) * 2 + 1); -int i = 0; -for(;*str && isspace(*str);str++) - ; while(*str) - { - matchStr[i++] = '+'; - for(; *str && !isspace(*str);str++) - matchStr[i++] = *str; - for(;*str && isspace(*str);str++) - ; - } -matchStr[i++] = 0; -return matchStr; -} - -struct pubsExtra -/* additional info needed for publication blat linked features: author+year and title */ -{ - char* label; - char* mouseOver; -}; - -static char* pubsFeatureLabel(char* author, char* year) -/* create label <author><year> given authors and year strings */ -{ -char* authorYear = NULL; - -if (isEmpty(author)) - author = "NoAuthor"; -if (isEmpty(year)) - year = "NoYear"; -authorYear = catTwoStrings(author, year); - -return authorYear; -} - -static struct pubsExtra *pubsMakeExtra(char* articleTable, struct sqlConnection* conn, - struct linkedFeatures* lf) -{ -char query[LARGEBUF]; -struct sqlResult *sr = NULL; -char **row = NULL; -struct pubsExtra *extra = NULL; - -safef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", - articleTable, lf->name); -sr = sqlGetResult(conn, query); -if ((row = sqlNextRow(sr)) != NULL) -{ - char* firstAuthor = row[0]; - char* year = row[1]; - char* title = row[2]; - - extra = needMem(sizeof(struct pubsExtra)); - extra->label = pubsFeatureLabel(firstAuthor, year); - if (isEmpty(title)) - extra->mouseOver = extra->label; - else - extra->mouseOver = cloneString(title); -} - -sqlFreeResult(&sr); -return extra; -} - -static void pubsAddExtra(struct track* tg, struct linkedFeatures* lf) -/* add authorYear and title to linkedFeatures->extra */ -{ -char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable"); -if(isEmpty(articleTable)) - return; -if (lf->extra != NULL) - return; - -struct sqlConnection *conn = hAllocConn(database); -struct pubsExtra* extra = pubsMakeExtra(articleTable, conn, lf); -lf->extra = extra; -hFreeConn(&conn); -} - -static void pubsLoadKeywordYearItems(struct track *tg) -/* load items that fulfill keyword and year filter */ -{ -struct sqlConnection *conn = hAllocConn(database); -char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsKeywords"); -char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsYear"); -char *articleTable = pubsArticleTable(tg); - -if(yearFilter == NULL || sameWord(yearFilter, "anytime")) - yearFilter = NULL; - -if(isNotEmpty(keywords)) - keywords = makeMysqlMatchStr(sqlEscapeString(keywords)); - -if(isEmpty(yearFilter) && isEmpty(keywords)) -{ - loadGappedBed(tg); -} -else - { - char* oldLabel = tg->longLabel; - tg->longLabel = catTwoStrings(oldLabel, " (filter activated)"); - freeMem(oldLabel); - - char extra[2048], yearWhere[256], keywordsWhere[1024], prefix[256]; - char **row; - struct linkedFeatures *lfList = NULL; - struct trackDb *tdb = tg->tdb; - int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); - int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); - boolean useItemRgb = bedItemRgb(tdb); - - safef(prefix, sizeof(prefix), "name IN (SELECT articleId FROM %s WHERE", articleTable); - if(isNotEmpty(keywords)) - safef(keywordsWhere, sizeof(keywordsWhere), \ - "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE)", keywords); - if(isNotEmpty(yearFilter)) - safef(yearWhere, sizeof(yearWhere), "year >= '%s'", sqlEscapeString(yearFilter)); - - if(isEmpty(keywords)) - safef(extra, sizeof(extra), "%s %s)", prefix, yearWhere); - else if(isEmpty(yearFilter)) - safef(extra, sizeof(extra), "%s %s)", prefix, keywordsWhere); - else - safef(extra, sizeof(extra), "%s %s AND %s)", prefix, yearWhere, keywordsWhere); - - int rowOffset = 0; - struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra, - FALSE, NULL, &rowOffset); - while ((row = sqlNextRow(sr)) != NULL) - { - struct bed *bed = bedLoad12(row+rowOffset); - slAddHead(&lfList, bedMungToLinkedFeatures(&bed, tdb, 12, scoreMin, scoreMax, useItemRgb)); - } - sqlFreeResult(&sr); - slReverse(&lfList); - slSort(&lfList, linkedFeaturesCmp); - tg->items = lfList; - } -hFreeConn(&conn); -} - -#define PUBSFILTERNAME "pubsFilterArticleId" - -static void activatePslTrackIfCgi(struct track *tg) -/* the publications hgc creates links back to the browser with - * the cgi param pubsFilterArticleId to show only a single type - * of feature for the pubsBlatPsl track. - * If the parameter was supplied, we save this parameter here - * into the cart and activate the track. - */ -{ -char *articleId = cgiOptionalString(PUBSFILTERNAME); -//if (articleId==NULL) - //articleId = cartOptionalString(cart, PUBSFILTERNAME); - -if (articleId!=NULL) -{ - cartSetString(cart, PUBSFILTERNAME, articleId); - tdbSetCartVisibility(tg->tdb, cart, hCarefulTrackOpenVis(database, tg->track)); - tg->visibility=tvPack; -} -} - -char *pubsItemName(struct track *tg, void *item) -/* get author/year from extra field */ -{ -struct linkedFeatures *lf = item; -pubsAddExtra(tg, lf); - -struct pubsExtra* extra = lf->extra; -if (extra!=NULL) - return extra->label; -else - return lf->name; - -} - -static void pubsMapItem(struct track *tg, struct hvGfx *hvg, void *item, - char *itemName, char *mapItemName, int start, int end, - int x, int y, int width, int height) -/* create mouse over with title for pubs blat features. */ -{ -if (!theImgBox || tg->limitedVis != tvDense || !tdbIsCompositeChild(tg->tdb)) -{ - struct linkedFeatures *lf = item; - pubsAddExtra(tg, lf); - struct pubsExtra* extra = lf->extra; - char* mouseOver = NULL; - if (extra != NULL) - mouseOver = extra->mouseOver; - else - mouseOver = itemName; - - mapBoxHc(hvg, start, end, x, y, width, height, tg->track, mapItemName, mouseOver); -} -} - -static void pubsLoadMarkerItem (struct track *tg) -/* copy item names into extra field */ -{ -//loadSimpleBed(tg); -loadSimpleBedAsLinkedFeaturesPerBase(tg); -//tg->items = simpleBedListToLinkedFeatures(tg->items, tg->bedSize, TRUE, FALSE); -//if (! (hashFindVal(tdb->settingsHash, "pubsMarkerTable"))) -enum trackVisibility vis = tg->visibility; -if (vis == tvDense || vis == tvSquish) - return; - -struct linkedFeatures *lf = NULL; -for (lf = tg->items; lf != NULL; lf = lf->next) - lf->extra = lf->name; -} - -char *pubsMarkerItemName(struct track *tg, void *item) -/* retrieve article count from score field and return.*/ -{ -struct linkedFeatures *lf = item; -char newName[64]; -safef(newName, sizeof(newName), "%d articles", (int) lf->score); -return cloneString(newName); -} - -static void pubsMarkerMapItem(struct track *tg, struct hvGfx *hvg, void *item, - char *itemName, char *mapItemName, int start, int end, - int x, int y, int width, int height) -{ -struct linkedFeatures *lf = item; -genericMapItem(tg, hvg, item, - lf->extra, lf->extra, start, end, - x, y, width, height); -} - -static struct hash* pubsLookupSequences(struct track *tg, struct sqlConnection* conn, char* articleId, bool getSnippet) -/* create a hash with a mapping annotId -> snippet or annotId -> shortSeq for an articleId*/ -{ - char query[LARGEBUF]; - char *sequenceTable = trackDbRequiredSetting(tg->tdb, "pubsSequenceTable"); - char *selectValSql = NULL; - if (getSnippet) - selectValSql = "replace(replace(snippet, \"<B>\", \"\\n>>> \"), \"</B>\", \" <<<\\n\")"; - else - selectValSql = "concat(substr(sequence,1,4),\"...\",substr(sequence,-4))"; - - safef(query, sizeof(query), "SELECT annotId, %s FROM %s WHERE articleId='%s' ", - selectValSql, sequenceTable, articleId); - struct hash *seqIdHash = sqlQuickHash(conn, query); - //freeMem(sequenceTable); // XX Why does this crash?? - return seqIdHash; -} - -static char *pubsArticleDispId(struct track *tg, struct sqlConnection *conn, char* articleId) -/* given an articleId, lookup author and year and create <author><year> label for it */ -{ -char* dispLabel = NULL; -char *articleTable = pubsArticleTable(tg); -char query[LARGEBUF]; -safef(query, sizeof(query), "SELECT firstAuthor, year FROM %s WHERE articleId = '%s'", - articleTable, articleId); -struct sqlResult *sr = sqlGetResult(conn, query); -if (sr!=NULL) - { - char **row = NULL; - row = sqlNextRow(sr); - if (row != NULL) - dispLabel = pubsFeatureLabel(row[0], row[1]); - else - dispLabel = articleId; - } -else - dispLabel = articleId; -sqlFreeResult(&sr); -return dispLabel; -} - -static void pubsPslLoadItems(struct track *tg) -/* load only psl items from a single article */ -{ -// get articleId to filter on -char *articleId = cartOptionalString(cart, PUBSFILTERNAME); -if (articleId==NULL) - return; - -struct sqlConnection *conn = hAllocConn(database); -char* dispLabel = pubsArticleDispId(tg, conn, articleId); -struct hash *idToSnip = pubsLookupSequences(tg, conn, articleId, TRUE); -struct hash *idToSeq = pubsLookupSequences(tg, conn, articleId, FALSE); - -// change track label -char* oldLabel = tg->longLabel; -tg->longLabel = catTwoStrings("Individual matches for article ", dispLabel); -freeMem(oldLabel); - -// filter and load items for this articleId -char where[256]; -safef(where, sizeof(where), " articleId=%s ", articleId); - -int rowOffset = 0; -struct sqlResult *sr = NULL; -sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, where, &rowOffset); - -struct linkedFeatures *lfList = NULL; -char **row = NULL; -while ((row = sqlNextRow(sr)) != NULL) - { - struct psl *psl = pslLoad(row+rowOffset); - slAddHead(&lfList, lfFromPsl(psl, TRUE)); - char* shortSeq = hashFindVal(idToSeq, lfList->name); - char* snip = hashFindVal(idToSnip, lfList->name); - struct pubsExtra *extra = needMem(sizeof(struct pubsExtra)); - extra->mouseOver=snip; - extra->label=shortSeq; - lfList->extra = extra; - } -sqlFreeResult(&sr); -slReverse(&lfList); -slSort(&lfList, linkedFeaturesCmp); -tg->items = lfList; -hFreeConn(&conn); -} - -static void pubsBlatPslMethods(struct track *tg) -/* a track that shows only the indiv matches for one single article */ -{ -activatePslTrackIfCgi(tg); -tg->loadItems = pubsPslLoadItems; -tg->itemName = pubsItemName; -tg->mapItem = pubsMapItem; -} - -static void pubsBlatMethods(struct track *tg) -/* publication blat tracks are bed12+2 tracks of sequences in text, mapped with BLAT */ -{ -//bedMethods(tg); -tg->loadItems = pubsLoadKeywordYearItems; -tg->itemName = pubsItemName; -tg->mapItem = pubsMapItem; -} - -static void pubsMarkerMethods(struct track *tg) -/* publication marker tracks are bed5 tracks of genome marker occurences like rsXXXX found in text*/ -{ -//bedMethods(tg); -tg->bedSize = 5; -tg->loadItems = pubsLoadMarkerItem; -tg->mapItem = pubsMarkerMapItem; -tg->itemName = pubsMarkerItemName; -} - void fillInFromType(struct track *track, struct trackDb *tdb) /* Fill in various function pointers in track from type field of tdb. */ { char *typeLine = tdb->type, *words[8], *type; int wordCount; if (typeLine == NULL) return; wordCount = chopLine(cloneString(typeLine), words); if (wordCount <= 0) return; type = words[0]; #ifndef GBROWSE if (sameWord(type, "bed")) { @@ -12539,108 +12553,136 @@ /* else if (sameWord(type, "bedLogR")) { wordCount++; words[1] = "9"; complexBedMethods(track, tdb, FALSE, wordCount, words); //track->bedSize = 10; } */ else if (sameWord(type, "bigBed")) { bigBedMethods(track, tdb, wordCount, words); if (trackShouldUseAjaxRetrieval(track)) track->loadItems = dontLoadItems; } +else if (sameWord(type, "bigGenePred")) + { + tdb->canPack = TRUE; + wordCount++; + words[1] = "12"; + bigBedMethods(track, tdb, wordCount, words); + if (trackShouldUseAjaxRetrieval(track)) + track->loadItems = dontLoadItems; + } else if (sameWord(type, "bedGraph")) { bedGraphMethods(track, tdb, wordCount, words); } else if (sameWord(type, "bigWig")) { bigWigMethods(track, tdb, wordCount, words); if (trackShouldUseAjaxRetrieval(track)) track->loadItems = dontLoadItems; // TODO: Dummy drawItems as well? } else #endif /* GBROWSE */ if (sameWord(type, "wig")) { wigMethods(track, tdb, wordCount, words); } else if (startsWith("wigMaf", type)) { wigMafMethods(track, tdb, wordCount, words); } #ifndef GBROWSE else if (sameWord(type, "sample")) { sampleMethods(track, tdb, wordCount, words); } else if (sameWord(type, "genePred")) { linkedFeaturesMethods(track); + if (startsWith("ensGene", track->track)) + track->loadItems = loadGenePredEnsGene; + else track->loadItems = loadGenePred; track->colorShades = NULL; if (track->itemAttrTbl != NULL) track->itemColor = genePredItemAttrColor; else if (trackDbSetting(track->tdb, GENEPRED_CLASS_TBL) !=NULL) track->itemColor = genePredItemClassColor; } else if (sameWord(type, "logo")) { logoMethods(track, tdb, wordCount, words); } #endif /* GBROWSE */ else if (sameWord(type, "psl")) { pslMethods(track, tdb, wordCount, words); // FIXME: registerTrackHandler doesn't accept wildcards, so this might be the only // way to get this done in a general way. If this was in loaded with registerTrackHandler // pslMethods would need the tdb object, which we don't have for these callbacks if (startsWith("pubs", track->track)) pubsBlatPslMethods(track); } +#ifdef NOTNOW else if (sameWord(type, "snake")) { snakeMethods(track, tdb, wordCount, words); } +#endif else if (sameWord(type, "chain")) { chainMethods(track, tdb, wordCount, words); } else if (sameWord(type, "netAlign")) { netMethods(track); } else if (sameWord(type, "maf")) { mafMethods(track); } else if (sameWord(type, "bam")) { bamMethods(track); if (trackShouldUseAjaxRetrieval(track)) track->loadItems = dontLoadItems; } +#ifdef USE_HAL +else if (sameWord(type, "halSnake")) + { + halSnakeMethods(track, tdb, wordCount, words); + if (trackShouldUseAjaxRetrieval(track)) + track->loadItems = dontLoadItems; + } +#endif else if (sameWord(type, "vcfTabix")) { vcfTabixMethods(track); if (trackShouldUseAjaxRetrieval(track)) track->loadItems = dontLoadItems; } +else if (sameWord(type, "vcf")) + { + vcfMethods(track); + if (trackShouldUseAjaxRetrieval(track)) + track->loadItems = dontLoadItems; + } else if (startsWith(type, "bedDetail")) { bedDetailMethods(track); } else if (sameWord(type, "pgSnp")) { pgSnpCtMethods(track); } #ifndef GBROWSE else if (sameWord(type, "coloredExon")) { coloredExonMethods(track); } else if (sameWord(type, "axt")) { @@ -12706,48 +12748,52 @@ { remoteMethods(track); } else if (sameWord(type, "bamWig")) { bamWigMethods(track, tdb, wordCount, words); } else if (sameWord(type, "interaction")) { interactionMethods(track); } else if (sameWord(type, "gvf")) { gvfMethods(track); } +/* add handlers for wildcard */ +if (startsWith("peptideAtlas", track->track)) + peptideAtlasMethods(track); #endif /* GBROWSE */ } static void compositeLoad(struct track *track) /* Load all subtracks */ { struct track *subtrack; long thisTime = 0, lastTime = 0; for (subtrack = track->subtracks; subtrack != NULL; subtrack = subtrack->next) { if (isSubtrackVisible(subtrack) && ( limitedVisFromComposite(subtrack) != tvHide)) { if (!subtrack->parallelLoading) { lastTime = clock1000(); if (!subtrack->loadItems) // This could happen if track type has no handler (eg, for new types) errAbort("Error: No loadItems() handler for subtrack (%s) of composite track (%s) (is this a new track 'type'?)\n", subtrack->track, track->track); + checkIfWiggling(cart, subtrack); subtrack->loadItems(subtrack); if (measureTiming) { thisTime = clock1000(); subtrack->loadTime = thisTime - lastTime; lastTime = thisTime; } } } else { subtrack->limitedVis = tvHide; subtrack->limitedVisSet = TRUE; } } @@ -12941,41 +12987,41 @@ else track->colorShades = shadesOfGray; } track->tdb = tdb; /* Handle remote database settings - just a JK experiment at the moment. */ track->remoteSqlHost = trackDbSetting(tdb, "sqlHost"); track->remoteSqlUser = trackDbSetting(tdb, "sqlUser"); track->remoteSqlPassword = trackDbSetting(tdb, "sqlPassword"); track->remoteSqlDatabase = trackDbSetting(tdb, "sqlDatabase"); track->remoteSqlTable = trackDbSetting(tdb, "sqlTable"); track->isRemoteSql = (track->remoteSqlHost != NULL && track->remoteSqlUser != NULL && track->remoteSqlDatabase != NULL && track->remoteSqlTable !=NULL); exonArrows = trackDbSetting(tdb, "exonArrows"); -nextItem = trackDbSetting(tdb, "nextItemButton"); /* default exonArrows to on, except for tracks in regulation/expression group */ if (exonArrows == NULL) { if (sameString(tdb->grp, "regulation")) exonArrows = "off"; else exonArrows = "on"; } track->exonArrows = sameString(exonArrows, "on"); track->nextExonButtonable = TRUE; +nextItem = trackDbSetting(tdb, "nextItemButton"); if (nextItem && sameString(nextItem, "off")) track->nextExonButtonable = FALSE; track->nextItemButtonable = track->nextExonButtonable; #ifndef GBROWSE char *iatName = trackDbSetting(tdb, "itemAttrTbl"); if (iatName != NULL) track->itemAttrTbl = itemAttrTblNew(iatName); #endif /* GBROWSE */ fillInFromType(track, tdb); return track; } struct hash *handlerHash; void registerTrackHandler(char *name, TrackHandler handler) @@ -13006,80 +13052,114 @@ } TrackHandler lookupTrackHandlerClosestToHome(struct trackDb *tdb) /* Lookup handler for track of give name. Try parents if * subtrack has a NULL handler. Return NULL if none. */ { TrackHandler handler = lookupTrackHandler(tdb->table); // while handler is NULL and we have a parent, use the parent's handler for( ; (handler == NULL) && (tdb->parent != NULL); ) { tdb = tdb->parent; handler = lookupTrackHandler(tdb->table); } +// if nothing found, try the "trackHandler" statement +if (handler == NULL) + { + char *handlerName = trackDbSetting(tdb, "trackHandler"); + if (handlerName != NULL) + { + handler = lookupTrackHandler(handlerName); + if (handler==NULL) + errAbort("track %s defined a trackHandler in trackDb which does not exist", tdb->track); + } + } + return handler; } void registerTrackHandlers() /* Register tracks that include some non-standard methods. */ { #ifndef GBROWSE registerTrackHandler("rgdGene", rgdGeneMethods); registerTrackHandler("cgapSage", cgapSageMethods); registerTrackHandler("cytoBand", cytoBandMethods); registerTrackHandler("cytoBandIdeo", cytoBandIdeoMethods); + registerTrackHandler("bacEndPairs", bacEndPairsMethods); -registerTrackHandler("bacEndPairsBad", bacEndPairsBadMethods); -registerTrackHandler("bacEndPairsLong", bacEndPairsLongMethods); -registerTrackHandler("bacEndSingles", bacEndSinglesMethods); -registerTrackHandler("fosEndPairs", fosEndPairsMethods); -registerTrackHandler("fosEndPairsBad", fosEndPairsBadMethods); -registerTrackHandler("fosEndPairsLong", fosEndPairsLongMethods); -registerTrackHandler("earlyRep", earlyRepMethods); -registerTrackHandler("earlyRepBad", earlyRepBadMethods); +registerTrackHandler("bacEndPairsBad", bacEndPairsMethods); +registerTrackHandler("bacEndPairsLong", bacEndPairsMethods); +registerTrackHandler("bacEndSingles", bacEndPairsMethods); +registerTrackHandler("fosEndPairs", bacEndPairsMethods); +registerTrackHandler("fosEndPairsBad", bacEndPairsMethods); +registerTrackHandler("fosEndPairsLong", bacEndPairsMethods); +registerTrackHandler("earlyRep", bacEndPairsMethods); +registerTrackHandler("earlyRepBad", bacEndPairsMethods); + registerTrackHandler("genMapDb", genMapDbMethods); registerTrackHandler("cgh", cghMethods); registerTrackHandler("mcnBreakpoints", mcnBreakpointsMethods); registerTrackHandler("fishClones", fishClonesMethods); registerTrackHandler("mapGenethon", genethonMethods); registerTrackHandler("stsMarker", stsMarkerMethods); registerTrackHandler("stsMap", stsMapMethods); registerTrackHandler("stsMapMouseNew", stsMapMouseMethods); registerTrackHandler("stsMapRat", stsMapRatMethods); registerTrackHandler("snpMap", snpMapMethods); registerTrackHandler("snp", snpMethods); registerTrackHandler("snp125", snp125Methods); registerTrackHandler("snp126", snp125Methods); registerTrackHandler("snp127", snp125Methods); registerTrackHandler("snp128", snp125Methods); registerTrackHandler("snp129", snp125Methods); registerTrackHandler("snp130", snp125Methods); registerTrackHandler("snp131", snp125Methods); registerTrackHandler("snp132", snp125Methods); registerTrackHandler("snp132Common", snp125Methods); registerTrackHandler("snp132Flagged", snp125Methods); registerTrackHandler("snp132Mult", snp125Methods); registerTrackHandler("snp134", snp125Methods); registerTrackHandler("snp134Common", snp125Methods); registerTrackHandler("snp134Flagged", snp125Methods); registerTrackHandler("snp134Mult", snp125Methods); registerTrackHandler("snp135", snp125Methods); registerTrackHandler("snp135Common", snp125Methods); registerTrackHandler("snp135Flagged", snp125Methods); registerTrackHandler("snp135Mult", snp125Methods); +registerTrackHandler("snp137", snp125Methods); +registerTrackHandler("snp137Common", snp125Methods); +registerTrackHandler("snp137Flagged", snp125Methods); +registerTrackHandler("snp137Mult", snp125Methods); +registerTrackHandler("snp138", snp125Methods); +registerTrackHandler("snp138Common", snp125Methods); +registerTrackHandler("snp138Flagged", snp125Methods); +registerTrackHandler("snp138Mult", snp125Methods); +registerTrackHandler("snp139", snp125Methods); +registerTrackHandler("snp139Common", snp125Methods); +registerTrackHandler("snp139Flagged", snp125Methods); +registerTrackHandler("snp139Mult", snp125Methods); +registerTrackHandler("snp141", snp125Methods); +registerTrackHandler("snp141Common", snp125Methods); +registerTrackHandler("snp141Flagged", snp125Methods); +registerTrackHandler("snp141Mult", snp125Methods); +registerTrackHandler("snp142", snp125Methods); +registerTrackHandler("snp142Common", snp125Methods); +registerTrackHandler("snp142Flagged", snp125Methods); +registerTrackHandler("snp142Mult", snp125Methods); registerTrackHandler("ld", ldMethods); registerTrackHandler("cnpSharp", cnpSharpMethods); registerTrackHandler("cnpSharp2", cnpSharp2Methods); registerTrackHandler("cnpIafrate", cnpIafrateMethods); registerTrackHandler("cnpIafrate2", cnpIafrate2Methods); registerTrackHandler("cnpSebat", cnpSebatMethods); registerTrackHandler("cnpSebat2", cnpSebat2Methods); registerTrackHandler("cnpFosmid", cnpFosmidMethods); registerTrackHandler("cnpRedon", cnpRedonMethods); registerTrackHandler("cnpLocke", cnpLockeMethods); registerTrackHandler("cnpTuzun", cnpTuzunMethods); registerTrackHandler("delConrad", delConradMethods); registerTrackHandler("delConrad2", delConrad2Methods); registerTrackHandler("delMccarroll", delMccarrollMethods); registerTrackHandler("delHinds", delHindsMethods); @@ -13178,67 +13258,70 @@ registerTrackHandler("flyBaseGene", flyBaseGeneMethods); registerTrackHandler("flyBaseNoncoding", flyBaseGeneMethods); registerTrackHandler("sgdGene", sgdGeneMethods); registerTrackHandler("genieAlt", genieAltMethods); registerTrackHandler("ensGeneNonCoding", ensGeneNonCodingMethods); registerTrackHandler("mrna", mrnaMethods); registerTrackHandler("intronEst", estMethods); registerTrackHandler("est", estMethods); registerTrackHandler("all_est", estMethods); registerTrackHandler("all_mrna", mrnaMethods); registerTrackHandler("interPro", interProMethods); registerTrackHandler("tightMrna", mrnaMethods); registerTrackHandler("tightEst", mrnaMethods); registerTrackHandler("cpgIsland", cpgIslandMethods); registerTrackHandler("cpgIslandExt", cpgIslandMethods); +registerTrackHandler("cpgIslandExtUnmasked", cpgIslandMethods); registerTrackHandler("cpgIslandGgfAndy", cpgIslandMethods); registerTrackHandler("cpgIslandGgfAndyMasked", cpgIslandMethods); registerTrackHandler("exoMouse", exoMouseMethods); registerTrackHandler("pseudoMrna", xenoMrnaMethods); registerTrackHandler("pseudoMrna2", xenoMrnaMethods); registerTrackHandler("mrnaBlastz", xenoMrnaMethods); registerTrackHandler("mrnaBlastz2", xenoMrnaMethods); registerTrackHandler("xenoBlastzMrna", xenoMrnaMethods); registerTrackHandler("xenoBestMrna", xenoMrnaMethods); registerTrackHandler("xenoMrna", xenoMrnaMethods); registerTrackHandler("xenoEst", xenoMrnaMethods); registerTrackHandler("exoFish", exoFishMethods); registerTrackHandler("tet_waba", tetWabaMethods); registerTrackHandler("wabaCbr", cbrWabaMethods); registerTrackHandler("rnaGene", rnaGeneMethods); registerTrackHandler("encodeRna", encodeRnaMethods); registerTrackHandler("wgRna", wgRnaMethods); registerTrackHandler("ncRna", ncRnaMethods); registerTrackHandler("rmskLinSpec", repeatMethods); registerTrackHandler("rmsk", repeatMethods); registerTrackHandler("rmskNew", repeatMethods); +registerTrackHandler("joinedRmsk", rmskJoinedMethods); +registerTrackHandler("rmskJoinedBaseline", rmskJoinedMethods); +registerTrackHandler("rmskJoinedCurrent", rmskJoinedMethods); registerTrackHandler("rmskCensor", repeatMethods); registerTrackHandler("simpleRepeat", simpleRepeatMethods); registerTrackHandler("chesSimpleRepeat", simpleRepeatMethods); registerTrackHandler("uniGene",uniGeneMethods); registerTrackHandler("perlegen",perlegenMethods); registerTrackHandler("haplotype",haplotypeMethods); registerTrackHandler("encodeErge5race",encodeErgeMethods); registerTrackHandler("encodeErgeBinding",encodeErgeMethods); registerTrackHandler("encodeErgeExpProm",encodeErgeMethods); registerTrackHandler("encodeErgeHssCellLines",encodeErgeMethods); registerTrackHandler("encodeErgeInVitroFoot",encodeErgeMethods); registerTrackHandler("encodeErgeMethProm",encodeErgeMethods); registerTrackHandler("encodeErgeStableTransf",encodeErgeMethods); registerTrackHandler("encodeErgeSummary",encodeErgeMethods); registerTrackHandler("encodeErgeTransTransf",encodeErgeMethods); -registerTrackHandler("encodeGencodeGenePolyAMar07",bed9Methods); registerTrackHandlerOnFamily("encodeStanfordNRSF",encodeStanfordNRSFMethods); registerTrackHandler("cghNci60", cghNci60Methods); registerTrackHandler("rosetta", rosettaMethods); registerTrackHandler("affy", affyMethods); registerTrackHandler("ancientR", ancientRMethods ); registerTrackHandler("altGraphX", altGraphXMethods ); registerTrackHandler("triangle", triangleMethods ); registerTrackHandler("triangleSelf", triangleMethods ); registerTrackHandler("transfacHit", triangleMethods ); registerTrackHandler("esRegGeneToMotif", eranModuleMethods ); registerTrackHandler("leptin", mafMethods ); registerTrackHandler("igtc", igtcMethods ); registerTrackHandler("cactusBed", cactusBedMethods ); registerTrackHandler("variome", variomeMethods); /* Lowe lab related */ @@ -13297,82 +13380,58 @@ registerTrackHandler("encodeEvoFold", rnaSecStrMethods); registerTrackHandler("rnafold", rnaSecStrMethods); registerTrackHandler("mcFolds", rnaSecStrMethods); registerTrackHandler("rnaEditFolds", rnaSecStrMethods); registerTrackHandler("altSpliceFolds", rnaSecStrMethods); registerTrackHandler("chimpSimpleDiff", chimpSimpleDiffMethods); registerTrackHandler("tfbsCons", tfbsConsMethods); registerTrackHandler("tfbsConsSites", tfbsConsSitesMethods); registerTrackHandler("pscreen", simpleBedTriangleMethods); registerTrackHandler("dless", dlessMethods); registerTrackHandler("jaxAllele", jaxAlleleMethods); registerTrackHandler("jaxPhenotype", jaxPhenotypeMethods); registerTrackHandler("jaxAlleleLift", jaxAlleleMethods); registerTrackHandler("jaxPhenotypeLift", jaxPhenotypeMethods); /* ENCODE related */ -registerTrackHandlerOnFamily("wgEncodeGencode", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeSangerGencode", gencodeGeneMethods); -// one per gencode version, after V7 when it was substantially changed -// FIXME: this is hacky, need a way to register based on pattern -registerTrackHandlerOnFamily("wgEncodeGencodeV3", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV4", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV7", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV8", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV9", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV10", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV11", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV12", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV13", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV14", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeGencodeV15", gencodeGeneMethods); - -registerTrackHandlerOnFamily("wgEncodeSangerGencodeGencodeManual20081001", gencodeGeneMethods); -registerTrackHandlerOnFamily("wgEncodeSangerGencodeGencodeAuto20081001", gencodeGeneMethods); -registerTrackHandlerOnFamily("encodeGencodeGene", gencodeGeneMethods); -registerTrackHandlerOnFamily("encodeGencodeGeneJun05", gencodeGeneMethods); -registerTrackHandlerOnFamily("encodeGencodeGeneOct05", gencodeGeneMethods); -registerTrackHandlerOnFamily("encodeGencodeGeneMar07", gencodeGeneMethods); -registerTrackHandler("encodeGencodeIntron", gencodeIntronMethods); -registerTrackHandler("encodeGencodeIntronJun05", gencodeIntronMethods); -registerTrackHandler("encodeGencodeIntronOct05", gencodeIntronMethods); -registerTrackHandlerOnFamily("encodeGencodeRaceFrags", gencodeRaceFragsMethods); -registerTrackHandler("affyTxnPhase2", affyTxnPhase2Methods); +gencodeRegisterTrackHandlers(); +registerTrackHandler("affyTxnPhase2b", affyTxnPhase2Methods); registerTrackHandler("gvPos", gvMethods); registerTrackHandlerOnFamily("pgSnp", pgSnpMethods); registerTrackHandlerOnFamily("pgSnpHgwdev", pgSnpMethods); registerTrackHandlerOnFamily("pgPop", pgSnpMethods); registerTrackHandler("pgTest", pgSnpMethods); registerTrackHandler("protVarPos", protVarMethods); registerTrackHandler("oreganno", oregannoMethods); registerTrackHandler("encodeDless", dlessMethods); transMapRegisterTrackHandlers(); retroRegisterTrackHandlers(); registerTrackHandler("retroposons", dbRIPMethods); registerTrackHandlerOnFamily("kiddEichlerDisc", kiddEichlerMethods); registerTrackHandlerOnFamily("kiddEichlerValid", kiddEichlerMethods); registerTrackHandler("dgv", dgvMethods); registerTrackHandlerOnFamily("hapmapSnps", hapmapMethods); registerTrackHandlerOnFamily("hapmapSnpsPhaseII", hapmapMethods); registerTrackHandlerOnFamily("omicia", omiciaMethods); registerTrackHandler("omimGene", omimGeneMethods); registerTrackHandler("omimGene2", omimGene2Methods); registerTrackHandler("omimAvSnp", omimAvSnpMethods); registerTrackHandler("omimLocation", omimLocationMethods); registerTrackHandler("omimComposite", omimGene2Methods); registerTrackHandler("cosmic", cosmicMethods); registerTrackHandler("rest", restMethods); +registerTrackHandler("lrg", lrgMethods); #endif /* GBROWSE */ } void createHgFindMatchHash() /* Read from the cart the string assocated with matches and put the matching items into a hash for highlighting later. */ { char *matchLine = NULL; struct slName *nameList = NULL, *name = NULL; matchLine = cartOptionalString(cart, "hgFind.matches"); if(matchLine == NULL) return; nameList = slNameListFromString(matchLine,','); hgFindMatches = newHash(5); for(name = nameList; name != NULL; name = name->next)