78623774789ddc510785fe261c9d8298538a9ad6 hiram Thu Aug 8 11:48:30 2013 -0700 fixup to eliminate globals, passing data in tg structure refs #9741 #11384 diff --git src/hg/hgTracks/joinedRmskTrack.c src/hg/hgTracks/joinedRmskTrack.c index a31a033..16b11a7 100644 --- src/hg/hgTracks/joinedRmskTrack.c +++ src/hg/hgTracks/joinedRmskTrack.c @@ -10,43 +10,47 @@ #include "jksql.h" #include "hdb.h" #include "hgTracks.h" #include "rmskJoined.h" /* winBaseCount size ( or below ) at which the detailed view * of repeats is turned on. */ #define REPEAT_DETAIL_VIEW 100000 /* The maximum size of unaligned sequence to draw before * switching to the unscaled view: ie. "----//---" */ #define MAX_UNALIGNED_LEN 200 -/* Hash of the repeatItems ( tg->items ) for this track. +/* classHash is the hash of the repeatItems ( tg->items ) for this track. * This is used to hold display names for the lines of * the track, the line heights, and class colors. - */ -struct hash *classHash = NULL; -static struct repeatItem *otherRepeatItem = NULL; - -/* Hash of subtracks + * + * the subTracksHash is a hash of subtracks * The joinedRmskTrack is designed to be used as a composite track. * When jRepeatLoad is called this hash is populated with the * results of one or more table queries */ -struct hash *subTracksHash = NULL; +struct itemSpecifics +/* extra information to go with each track */ + { + struct hash *classHash; + struct repeatItem *otherRepeatItem; + struct hash *subTracksHash; + }; + struct subTrack { /* The number of display levels used in levels[] */ int levelCount; /* The rmskJoined records from table query */ struct rmskJoined *levels[30]; }; // Display names static char *rptClassNames[] = { "SINE", "LINE", "LTR", "DNA", "Simple", "Low Complexity", "Satellite", "RNA", "Other", "Unknown", }; // Data names @@ -86,68 +90,71 @@ static int cmpRepeatVisStart(const void *va, const void *vb) { const struct rmskJoined *a = *((struct rmskJoined **) va); const struct rmskJoined *b = *((struct rmskJoined **) vb); int aStart = a->chromStart; if (a->blockSizes[0] > MAX_UNALIGNED_LEN) aStart = a->chromStart + (a->blockSizes[0] - MAX_UNALIGNED_LEN); int bStart = b->chromStart; if (b->blockSizes[0] > MAX_UNALIGNED_LEN) bStart = b->chromStart + (b->blockSizes[0] - MAX_UNALIGNED_LEN); return (aStart - bStart); } /* Initialize the track */ -static struct repeatItem * -makeJRepeatItems() -{ +static void makeJRepeatItems(struct track *tg) /* Initialize the subtracks hash - This will eventually contain * all the repeat data for each displayed subtrack */ - subTracksHash = newHash(10); +{ + struct itemSpecifics *extraData; + AllocVar(extraData); + + extraData->classHash = newHash(6); + extraData->otherRepeatItem = NULL; + extraData->subTracksHash = newHash(10); + tg->extraUiData = extraData; - classHash = newHash(6); struct repeatItem *ri, *riList = NULL; int i; int numClasses = ArraySize(rptClasses); for (i = 0; i < numClasses; ++i) { AllocVar(ri); ri->class = rptClasses[i]; ri->className = rptClassNames[i]; // New color attribute ri->color = jRepeatClassColors[i]; slAddHead(&riList, ri); // Hash now prebuilt to hold color attributes - hashAdd(classHash, ri->class, ri); + hashAdd(extraData->classHash, ri->class, ri); if (sameString(rptClassNames[i], "Other")) - otherRepeatItem = ri; + extraData->otherRepeatItem = ri; } slReverse(&riList); - return riList; + tg->items = riList; } -static void -jRepeatLoad(struct track *tg) +static void jRepeatLoad(struct track *tg) /* We do the query(ies) here so we can report how deep the track(s) * will be when jRepeatTotalHeight() is called later on */ { - tg->items = makeJRepeatItems(); + makeJRepeatItems(tg); + struct itemSpecifics *extraData = tg->extraUiData; - fprintf(stderr, "Called jRepeatLoad: table = %s\n", tg->table ); int baseWidth = winEnd - winStart; if ( tg->visibility == tvFull && baseWidth <= REPEAT_DETAIL_VIEW) { struct subTrack *st = NULL; AllocVar(st); if ( st ) { st->levels[0] = NULL; struct rmskJoined *rm = NULL; char **row; int rowOffset; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset); @@ -214,31 +221,31 @@ crChromStart = cr->chromStart + (cr->blockSizes[0] - MAX_UNALIGNED_LEN); crChromEnd = cr->chromEnd; if (cr->blockSizes[cr->blockCount - 1] > MAX_UNALIGNED_LEN) crChromEnd -= (cr->blockSizes[cr->blockCount - 1] - MAX_UNALIGNED_LEN); } else { prev = rm; rm = rm->next; } } // while ( rm ) } // while ( detailList ) // Create Hash Entry - hashReplace(subTracksHash, tg->table, st); + hashReplace(extraData->subTracksHash, tg->table, st); } // if ( st ) } // if ( tg->visibility == tvFull } static void jRepeatFree(struct track *tg) /* Free up jRepeatMasker items. */ { slFreeList(&tg->items); } static char * jRepeatName(struct track *tg, void *item) /* Return name of jRepeat item track. */ { @@ -254,36 +261,37 @@ if (strcmp(ri->className, "SINE") == 0) { return ("Repeats"); } else { return ∅ } } return ri->className; } int jRepeatTotalHeight(struct track *tg, enum trackVisibility vis) { + struct itemSpecifics *extraData = tg->extraUiData; // Are we in full view mode and at the scale needed to display // the detail view? if (tg->limitedVis == tvFull && winBaseCount <= REPEAT_DETAIL_VIEW) { // Lookup the depth of this subTrack and report it - struct subTrack *st = hashFindVal(subTracksHash, tg->table ); + struct subTrack *st = hashFindVal(extraData->subTracksHash, tg->table ); if ( st ) return ( (st->levelCount+1) * 24 ); else // Just display one line return ( 24 ); } else return tgFixedTotalHeightNoOverflow(tg, vis); } int jRepeatItemHeight(struct track *tg, void *item) { // Are we in full view mode and at the scale needed to display // the detail view? @@ -563,31 +571,32 @@ * * Here is an example: * ie. * A forward strand RM annotation from chr1:186-196 * which is aligned to a 100 bp repeat from 75-84 * in the consensus would be represented as: * * chromStart: 111 * chromEnd: 212 * blockRelStarts: -1, 75, -1 * blockSizes: 75, 10, 16 * */ static void drawRMGlyph(struct hvGfx *hvg, int y, int heightPer, - int width, int baseWidth, int xOff, struct rmskJoined *rm) + int width, int baseWidth, int xOff, struct rmskJoined *rm, + struct itemSpecifics *extraData) { int idx; int lx1, lx2; int cx1, cx2; int w; struct repeatItem *ri; /* * heightPer is the God given height of a single * track item...respect your overlord. */ int alignedBlockHeight = heightPer * 0.5; int alignedBlockOffset = heightPer - alignedBlockHeight; int unalignedBlockHeight = heightPer * 0.75; int unalignedBlockOffset = heightPer - unalignedBlockHeight; @@ -607,33 +616,33 @@ char *slashPtr = index(class, '/'); if (slashPtr) *slashPtr = '\0'; } else { safecpy(class, sizeof(class), "Unknown"); } char *p = &(class[strlen(class) - 1]); if (*p == '?') *p = '\0'; if (endsWith(class, "RNA")) safecpy(class, sizeof(class), "RNA"); // Lookup the class to get the color scheme - ri = hashFindVal(classHash, class); + ri = hashFindVal(extraData->classHash, class); if (ri == NULL) - ri = otherRepeatItem; + ri = extraData->otherRepeatItem; // Pick the fill color based on the divergence int percId = 10000 - rm->score; int grayLevel = grayInRange(percId, 6000, 10000); fillColor = shadesOfGray[grayLevel]; outlineColor = ri->color; // Draw from left to right for (idx = 0; idx < rm->blockCount; idx++) { int fragGStart = rm->blockRelStarts[idx]; /* * Assumptions about blockCount * - first aligned block = 1, the block 0 is @@ -918,30 +927,31 @@ } } } } } /* This is the original repeat drawing routine, modified * to handle the new rmskJoined table structure. */ static void origRepeatDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont * font, Color color, enum trackVisibility vis) { + struct itemSpecifics *extraData = tg->extraUiData; int baseWidth = seqEnd - seqStart; struct repeatItem *ri; int y = yOff; int heightPer = tg->heightPer; int lineHeight = tg->lineHeight; int x1, x2, w; boolean isFull = (vis == tvFull); Color col; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; char **row; int rowOffset; if (isFull) { @@ -974,31 +984,31 @@ char *slashPtr = index(class, '/'); if (slashPtr) *slashPtr = '\0'; } else { safecpy(class, sizeof(class), "Unknown"); } char *p = &(class[strlen(class) - 1]); if (*p == '?') *p = '\0'; if (endsWith(class, "RNA")) safecpy(class, sizeof(class), "RNA"); ri = hashFindVal(hash, class); if (ri == NULL) - ri = otherRepeatItem; + ri = extraData->otherRepeatItem; percId = 10000 - ro->score; grayLevel = grayInRange(percId, 6000, 10000); col = shadesOfGray[grayLevel]; int idx = 0; for (idx = 0; idx < ro->blockCount; idx++) { if (ro->blockRelStarts[idx] > 0) { int blockStart = ro->chromStart + ro->blockRelStarts[idx]; int blockEnd = ro->chromStart + ro->blockRelStarts[idx] + ro->blockSizes[idx]; x1 = roundingScale(blockStart - winStart, width, baseWidth) + xOff; x1 = max(x1, 0); @@ -1072,59 +1082,60 @@ } dyStringFree(&query); } sqlFreeResult(&sr); hFreeConn(&conn); } /* Main callback for displaying this track in the viewport * of the browser. */ static void jRepeatDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont * font, Color color, enum trackVisibility vis) { + struct itemSpecifics *extraData = tg->extraUiData; int baseWidth = seqEnd - seqStart; /* * Its unclear to me why heightPer is not updated to the * value set in jRepeatItemHeight() at the time this callback * is invoked. Getting the correct value myself. * was: * int heightPer = tg->heightPer; */ int heightPer = jRepeatItemHeight(tg, NULL); boolean isFull = (vis == tvFull); struct rmskJoined *rm; // If we are in full view mode and the scale is sufficient, // display the new visualization. if (isFull && baseWidth <= REPEAT_DETAIL_VIEW) { int level = yOff; - struct subTrack *st = hashFindVal(subTracksHash, tg->table ); + struct subTrack *st = hashFindVal(extraData->subTracksHash, tg->table ); if ( ! st ) return; int lidx = st->levelCount; int currLevel = 0; for (currLevel = 0; currLevel < lidx; currLevel++) { rm = st->levels[currLevel]; while (rm) { - drawRMGlyph(hvg, level, heightPer, width, baseWidth, xOff, rm); + drawRMGlyph(hvg, level, heightPer, width, baseWidth, xOff, rm, extraData); char statusLine[128]; int ss1 = roundingScale(rm->alignStart - winStart, width, baseWidth) + xOff; safef(statusLine, sizeof(statusLine), "name: %s", rm->name ); int x1 = roundingScale(rm->alignStart - winStart, width, baseWidth) + xOff; x1 = max(x1, 0); int x2 = roundingScale(rm->alignEnd - winStart, width, baseWidth) + xOff; int w = x2 - x1; if (w <= 0) w = 1;