Esempio n. 1
0
void mapBoxForCenterVariant(struct vcfRecord *rec, struct hvGfx *hvg, struct track *tg,
			    int xOff, int yOff, int width)
/* Special mouseover for center variant */
{
struct dyString *dy = dyStringNew(0);
unsigned int chromStartMap = vcfRecordTrimIndelLeftBase(rec);
unsigned int chromEndMap = vcfRecordTrimAllelesRight(rec);
gtSummaryString(rec, dy);
dyStringAppend(dy, "   Haplotypes sorted on ");
char *centerChrom = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "centerVariantChrom");
if (centerChrom == NULL || !sameString(chromName, centerChrom))
    dyStringAppend(dy, "middle variant by default. ");
else
    dyStringAppend(dy, "this variant. ");
dyStringAppend(dy, "To anchor sorting to a different variant, click on that variant and "
	       "then click on the 'Use this variant' button below the variant name.");
const double scale = scaleForPixels(width);
int x1 = round((double)(rec->chromStart-winStart)*scale) + xOff;
int x2 = round((double)(rec->chromEnd-winStart)*scale) + xOff;
int w = x2-x1;
if (w <= 1)
    {
    x1--;
    w = 3;
    }
mapBoxHgcOrHgGene(hvg, chromStartMap, chromEndMap, x1, yOff, w, tg->height, tg->track,
		  rec->name, dy->string, NULL, TRUE, NULL);
}
Esempio n. 2
0
enum wiggleGridOptEnum wigFetchTransformFuncWithCart(struct cart *theCart,
    struct trackDb *tdb, char *name,char **optString)
/*	transformFunc - none by default **********************************/
{
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *transformFunc;
enum wiggleTransformFuncEnum ret = wiggleTransformFuncNone;
char * tdbDefault = trackDbSettingClosestToHome(tdb, TRANSFORMFUNC);

transformFunc = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, 
                                                            TRANSFORMFUNC));

if ((transformFunc == NULL) && (tdbDefault != NULL))
    transformFunc = cloneString(tdbDefault);

if (optString && transformFunc)
    *optString = cloneString(transformFunc);

if (transformFunc)
    {
    ret = wiggleTransformFuncToEnum(transformFunc);
    freeMem(transformFunc);
    }
return((enum wiggleGridOptEnum)ret);
}
Esempio n. 3
0
enum wiggleAggregateFunctionEnum wigFetchAggregateFunctionWithCart(struct cart *theCart,
                                               struct trackDb *tdb, char *name, char **optString)
/****** windowingFunction - Whiskers by default **************************/
{
char *Default = wiggleAggregateFunctionEnumToString(wiggleAggregateTransparent);
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *aggregateFunction = NULL;
enum wiggleAggregateFunctionEnum ret;

aggregateFunction = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, 
                                                                AGGREGATE));

/*      If windowingFunction is a string, it came from the cart, otherwise
 *      see if it is specified in the trackDb option, finally
 *	return the default.
 */
if (!aggregateFunction)
    {
    char * tdbDefault =
        trackDbSettingClosestToHomeOrDefault(tdb, AGGREGATE, Default);

    freeMem(aggregateFunction);
    if (differentWord(Default,tdbDefault))
        aggregateFunction = cloneString(tdbDefault);
    else
	{
	struct hashEl *hel;
	/*	no aggregateFunction from trackDb, maybe it is in tdb->settings
	 *	(custom tracks keep settings here)
	 */
	aggregateFunction = cloneString(Default);
	if ((tdb->settings != (char *)NULL) &&
	    (tdb->settingsHash != (struct hash *)NULL))
	    {
	    if ((hel =hashLookup(tdb->settingsHash, AGGREGATE)) !=NULL)
		if (differentWord(Default,(char *)hel->val))
		    {
		    freeMem(aggregateFunction);
		    aggregateFunction = cloneString((char *)hel->val);
		    }
	    }
	}
    }

if (optString)
    *optString = cloneString(aggregateFunction);

ret = wiggleAggregateFunctionStringToEnum(aggregateFunction);
freeMem(aggregateFunction);
return(ret);
}       /*      enum wiggleWindowingEnum wigFetchWindowingFunctionWithCart() */
Esempio n. 4
0
void wigFetchYLineMarkValueWithCart(struct cart *theCart,struct trackDb *tdb, char *name, double *tDbYMark )
/*      y= marker line value
 *      User requested value is defined in the cart
 *	A Default value can be defined as
 *		yLineMark declaration from trackDb
 *****************************************************************************/
{
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *yLineMarkValue = NULL;  /*	string from cart	*/
double yLineValue;   /*	value from cart or trackDb */
char * tdbDefault = cloneString(
    trackDbSettingClosestToHomeOrDefault(tdb, YLINEMARK, "NONE") );

if (sameWord("NONE",tdbDefault))
    {
    struct hashEl *hel;
    /*	no yLineMark from trackDb, maybe it is in tdb->settings
     *	(custom tracks keep settings here)
     */
    if ((tdb->settings != (char *)NULL) &&
	(tdb->settingsHash != (struct hash *)NULL))
	{
	if ((hel = hashLookup(tdb->settingsHash, YLINEMARK)) != NULL)
	    {
	    freeMem(tdbDefault);
	    tdbDefault = cloneString((char *)hel->val);
	    }
	}
    }

/*	If nothing else, it is zero	*/
yLineValue = 0.0;

/*      Let's see if a value is available in the cart */
yLineMarkValue = cartOptionalStringClosestToHome(theCart, tdb, parentLevel, YLINEMARK);

/*      if yLineMarkValue is non-Null, it is the requested value        */
if (yLineMarkValue)
    yLineValue = atof(yLineMarkValue);
else /*    See if a default line is specified in the trackDb.ra file */
    if (differentWord("NONE",tdbDefault))
	yLineValue = atof(tdbDefault);

/*	If possible to return	*/
if (tDbYMark)
	*tDbYMark = yLineValue;

freeMem(tdbDefault);
}       /*      void wigFetchYLineMarkValueWithCart()   */
Esempio n. 5
0
boolean wigFetchDoNegativeWithCart(struct cart *theCart, struct trackDb *tdb, char *name,char **optString)
/*	doNegative - false by default **********************************/
{
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *doNegativeDefault = trackDbSettingClosestToHome(tdb, DONEGATIVEMODE);
char *doNegative = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, DONEGATIVEMODE));

if ((doNegative == NULL) && (doNegativeDefault != NULL))
    doNegative = cloneString(doNegativeDefault);

if (doNegative == NULL)
    return FALSE;

return sameString(doNegative, "1") || sameString(doNegative, "on");
}
Esempio n. 6
0
enum wiggleSmoothingEnum wigFetchSmoothingWindowWithCart(struct cart *theCart, struct trackDb *tdb, 
                                                         char *name, char **optString)
/****** smoothingWindow - OFF by default **************************/
{
char * Default = wiggleSmoothingEnumToString(wiggleSmoothingOff);
boolean parentLevel = isNameAtParentLevel(tdb,name);
char * smoothingWindow = NULL;
enum wiggleSmoothingEnum ret;

smoothingWindow = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, 
                                                              SMOOTHINGWINDOW));

if (!smoothingWindow) /* if nothing from the Cart, check trackDb/settings */
    {
    char * tdbDefault =
        trackDbSettingClosestToHomeOrDefault(tdb, SMOOTHINGWINDOW, Default);


    if (differentWord(Default,tdbDefault))
        smoothingWindow = cloneString(tdbDefault);
    else
	{
	struct hashEl *hel;
	/*	no smoothingWindow from trackDb, maybe it is in tdb->settings
	 *	(custom tracks keep settings here)
	 */
	smoothingWindow = cloneString(Default);
	if ((tdb->settings != (char *)NULL) &&
	    (tdb->settingsHash != (struct hash *)NULL))
	    {
	    if ((hel = hashLookup(tdb->settingsHash, SMOOTHINGWINDOW)) != NULL)
		if (differentWord(Default,(char *)hel->val))
		    {
		    freeMem(smoothingWindow);
		    smoothingWindow = cloneString((char *)hel->val);
		    }
	    }
	}
    }

if (optString)
    *optString = cloneString(smoothingWindow);

ret = wiggleSmoothingStringToEnum(smoothingWindow);
freeMem(smoothingWindow);
return(ret);
}       /*      enum wiggleSmoothingEnum wigFetchSmoothingWindowWithCart()      */
Esempio n. 7
0
enum wiggleScaleOptEnum wigFetchAutoScaleWithCart(struct cart *theCart, struct trackDb *tdb, 
                                                  char *name, char **optString)
/****** autoScale - off by default ***************************************/
{
char *autoString = wiggleScaleEnumToString(wiggleScaleAuto);
char *manualString = wiggleScaleEnumToString(wiggleScaleManual);
char *Default = manualString;
char *notDefault = autoString;
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *autoScale = NULL;
enum wiggleScaleOptEnum ret;


autoScale = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, AUTOSCALE));

if (!autoScale) /*      if nothing from the Cart, check trackDb/settings */
    {
    /*  It may be the autoScale=on/off situation from custom tracks */
    char * tdbDefault = trackDbSettingClosestToHomeOrDefault(tdb, AUTOSCALE, "NONE");
    if (sameWord(tdbDefault,"on"))
	autoScale = cloneString(autoString);
    else if (sameWord(tdbDefault,"off"))
	autoScale = cloneString(manualString);
    else
	{
	if (isCustomTrack(tdb->track))
	    // backwards defaults for custom tracks, autoScale on
	    autoScale = wigCheckBinaryOption(tdb,notDefault,Default,
		AUTOSCALEDEFAULT, AUTOSCALE);
	else
	    autoScale = wigCheckBinaryOption(tdb,Default,notDefault,
		AUTOSCALEDEFAULT, AUTOSCALE);
	}
    }

if (optString)
    *optString = cloneString(autoScale);

ret = wiggleScaleStringToEnum(autoScale);
freeMem(autoScale);
return(ret);
}       /*      enum wiggleScaleOptEnum wigFetchAutoScaleWithCart()     */
Esempio n. 8
0
enum wiggleYLineMarkEnum wigFetchYLineMarkWithCart(struct cart *theCart, struct trackDb *tdb, 
                                                   char *name, char **optString)
/*      yLineMark - off by default **********************************/
{
char *Default = wiggleYLineMarkEnumToString(wiggleYLineMarkOff);
char *notDefault = wiggleYLineMarkEnumToString(wiggleYLineMarkOn);
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *yLineMark = NULL;
enum wiggleYLineMarkEnum ret;

yLineMark = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, YLINEONOFF));

if (!yLineMark) /*      if nothing from the Cart, check trackDb/settings */
    yLineMark = wigCheckBinaryOption(tdb,Default,notDefault,YLINEONOFF,
	(char *)NULL);

if (optString)
    *optString = cloneString(yLineMark);

ret = wiggleYLineMarkStringToEnum(yLineMark);
freeMem(yLineMark);
return(ret);
}       /*      enum wiggleYLineMarkEnum wigFetchYLineMarkWithCart()    */
Esempio n. 9
0
enum wiggleGraphOptEnum wigFetchGraphTypeWithCart(struct cart *theCart, struct trackDb *tdb, 
                                                  char *name, char **optString)
/****** graphType - line(points) or bar graph *****************************/
{
char *Default = wiggleGraphEnumToString(wiggleGraphBar);
char *notDefault = wiggleGraphEnumToString(wiggleGraphPoints);
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *graphType = NULL;
enum wiggleGraphOptEnum ret;

graphType = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, LINEBAR));

if (!graphType) /*      if nothing from the Cart, check trackDb/settings */
    graphType = wigCheckBinaryOption(tdb,Default,notDefault,GRAPHTYPEDEFAULT,
	GRAPHTYPE);

if (optString)
    *optString = cloneString(graphType);

ret = wiggleGraphStringToEnum(graphType);
freeMem(graphType);
return(ret);
}       /*      enum wiggleGraphOptEnum wigFetchGraphTypeWithCart()     */
Esempio n. 10
0
enum wiggleGridOptEnum wigFetchHorizontalGridWithCart(struct cart *theCart, struct trackDb *tdb, 
                                                      char *name,char **optString)
/* horizontalGrid - off by default **********************************/
{
char *Default = wiggleGridEnumToString(wiggleHorizontalGridOff);
char *notDefault = wiggleGridEnumToString(wiggleHorizontalGridOn);
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *horizontalGrid = NULL;
enum wiggleGridOptEnum ret;

horizontalGrid = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, HORIZGRID));

if (!horizontalGrid)    /*      if it is NULL   */
    horizontalGrid = wigCheckBinaryOption(tdb,Default,notDefault,GRIDDEFAULT,
	HORIZGRID);

if (optString)
    *optString = cloneString(horizontalGrid);

ret = wiggleGridStringToEnum(horizontalGrid);
freeMem(horizontalGrid);
return(ret);
}       /*      enum wiggleGridOptEnum wigFetchHorizontalGridWithCart() */
Esempio n. 11
0
static int getCenterVariantIx(struct track *tg, int seqStart, int seqEnd,
			      struct vcfRecord *records)
// If the user hasn't specified a local variant/position to use as center,
// just use the median variant in window.
{
int defaultIx = (slCount(records)-1) / 2;
char *centerChrom = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "centerVariantChrom");
if (centerChrom != NULL && sameString(chromName, centerChrom))
    {
    int centerPos = cartUsualIntClosestToHome(cart, tg->tdb, FALSE, "centerVariantPos", -1);
    int winSize = seqEnd - seqStart;
    if (centerPos > (seqStart - winSize) && centerPos < (seqEnd + winSize))
	{
	int i;
	struct vcfRecord *rec;
	for (rec = records, i = 0;  rec != NULL;  rec = rec->next, i++)
	    if (rec->chromStart >= centerPos)
		return i;
	return i-1;
	}
    }
return defaultIx;
}
Esempio n. 12
0
enum wiggleGridOptEnum wigFetchAlwaysZeroWithCart(struct cart *theCart,
    struct trackDb *tdb, char *name,char **optString)
/*	alwaysZero - off by default **********************************/
{
boolean parentLevel = isNameAtParentLevel(tdb,name);
char *alwaysZero;
enum wiggleAlwaysZeroEnum ret = wiggleAlwaysZeroOff;
char * tdbDefault = trackDbSettingClosestToHome(tdb, ALWAYSZERO);

alwaysZero = cloneString(cartOptionalStringClosestToHome(theCart, tdb, parentLevel, ALWAYSZERO));

if ((alwaysZero == NULL) && (tdbDefault != NULL))
    alwaysZero = cloneString(tdbDefault);

if (optString && alwaysZero)
    *optString = cloneString(alwaysZero);

if (alwaysZero)
    {
    ret = wiggleAlwaysZeroToEnum(alwaysZero);
    freeMem(alwaysZero);
    }
return((enum wiggleGridOptEnum)ret);
}
Esempio n. 13
0
void wigFetchMinMaxYWithCart(struct cart *theCart, struct trackDb *tdb, char *name,
                             double *retMin, double *retMax, double *retAbsMin, double *retAbsMax,
                             int wordCount, char **words)
/*****************************************************************************
 *	Min, Max Y viewing limits
 *	Absolute limits are defined on the trackDb type line for wiggle,
 *	or MIN_LIMIT / MAX_LIMIT trackDb settings for bedGraph
 *	User requested limits are defined in the cart
 *	Default opening display limits are optionally defined with the
 *		defaultViewLimits or viewLimits declaration from trackDb
 *****************************************************************************/
{
boolean isBedGraph = (wordCount == 0 || sameString(words[0],"bedGraph"));
// Determine absolute min and max.  Someday hgTrackDb will enforce inclusion of data
// range settings, but until then, there is some circular logic where either one
// can provide a default for the other if the other is missing.
double absMax = 0.0, absMin = 0.0;
boolean missingAbsMin = FALSE, missingAbsMax = FALSE;
if (isBedGraph)
    {
    char *tdbMin = trackDbSettingClosestToHomeOrDefault(tdb, MIN_LIMIT, NULL);
    char *tdbMax = trackDbSettingClosestToHomeOrDefault(tdb, MAX_LIMIT, NULL);
    if (tdbMin == NULL)
	missingAbsMin = TRUE;
    else
	absMin = sqlDouble(tdbMin);
    if (tdbMax == NULL)
	missingAbsMax = TRUE;
    else
	absMax = sqlDouble(tdbMax);
    }
else
    {
    // Wiggle: get min and max from type setting, which has been chopped into words and wordCount:
    // type wig <min> <max>
    if (wordCount >= 3)
	absMax = atof(words[2]);
    else
	missingAbsMax = TRUE;
    if (wordCount >= 2)
	absMin = atof(words[1]);
    else
	missingAbsMin = TRUE;
    }
correctOrder(absMin, absMax);

// Determine current minY,maxY.
// Precedence:  1. cart;  2. defaultViewLimits;  3. viewLimits;
//              4. absolute [which may need to default to #2 or #3!]
boolean parentLevel = isNameAtParentLevel(tdb, name);
char *cartMinStr = cartOptionalStringClosestToHome(theCart, tdb, parentLevel, MIN_Y);
char *cartMaxStr = cartOptionalStringClosestToHome(theCart, tdb, parentLevel, MAX_Y);
double cartMin = 0.0, cartMax = 0.0;

if(cartMinStr)
    *retMin = atof(cartMinStr);
if(cartMaxStr)
    *retMax = atof(cartMaxStr);
if (cartMinStr && cartMaxStr)
    correctOrder(*retMin, *retMax);
// If it weren't for the the allowance for missing data range values,
// we could set retAbs* and be done here.
if(cartMinStr)
    cartMin = *retMin;
if(cartMaxStr)
    cartMax = *retMax;

// Get trackDb defaults, and resolve missing wiggle data range if necessary.
char *defaultViewLimits = trackDbSettingClosestToHomeOrDefault(tdb, DEFAULTVIEWLIMITS, NULL);
if (defaultViewLimits == NULL)
    defaultViewLimits = trackDbSettingClosestToHomeOrDefault(tdb, VIEWLIMITS, NULL);
if (defaultViewLimits != NULL)
    {
    double viewLimitMin = 0.0, viewLimitMax = 0.0;
    parseColonRange(defaultViewLimits, &viewLimitMin, &viewLimitMax);
    *retMin = viewLimitMin;
    *retMax = viewLimitMax;
    if (missingAbsMax)
	absMax = viewLimitMax;
    if (missingAbsMin)
	absMin = viewLimitMin;
    }
else if (missingAbsMin || missingAbsMax)
    {
    if (isBedGraph)
	{
	absMin = DEFAULT_MIN_BED_GRAPH;
	absMax = DEFAULT_MAX_BED_GRAPH;
	}
    else
	{
	absMin = DEFAULT_MIN_Yv;
	absMax = DEFAULT_MAX_Yv;
	}
    *retMin = absMin;
    *retMax = absMax;
    }
else
    {
    *retMin = absMin;
    *retMax = absMax;
    }

if (retAbsMin)
    *retAbsMin = absMin;
if (retAbsMax)
    *retAbsMax = absMax;
// After the dust settles from tdb's trackDb settings, now see if composite view
// settings from tdb's parents override that stuff anyway:
viewLimitsCompositeOverride(tdb, name, retMin, retMax, retAbsMin, retAbsMax);

// And as the final word after composite override, reset retMin and retMax if from cart:
if (cartMinStr)
    *retMin = cartMin;
if (cartMaxStr)
    *retMax = cartMax;
}       /*      void wigFetchMinMaxYWithCart()  */
Esempio n. 14
0
static void pubsLoadKeywordYearItems(struct track *tg)
/* load items that fulfill keyword and year filter */
{
pubsParseClassColors();
struct sqlConnection *conn = hAllocConn(database);
char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterKeywords");
char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterYear");
char *publFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterPublisher");
char *articleTable = pubsArticleTable(tg);

if(sameOk(yearFilter, "anytime"))
    yearFilter = NULL;
if(sameOk(publFilter, "all"))
    publFilter = NULL;

if(isNotEmpty(keywords))
    keywords = makeMysqlMatchStr(keywords);

if (isEmpty(yearFilter) && isEmpty(keywords) && isEmpty(publFilter))
{
    loadGappedBed(tg);
}
else
    {
    // put together an "extra" query to hExtendedRangeQuery that removes articles
    // without the keywords specified in hgTrackUi
    char *oldLabel = tg->longLabel;
    tg->longLabel = catTwoStrings(oldLabel, " (filter activated)");
    freeMem(oldLabel);

    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);

    char *extra = NULL;
    struct dyString *extraDy = dyStringNew(0);
    struct hash *articleIds = searchForKeywords(conn, articleTable, keywords);
    if (!sameWord(tg->table, "pubsBlat"))
        // new table schema: filter fields are on main bed table
        {
        if (isNotEmpty(yearFilter))
            sqlDyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", yearFilter);
        if (isNotEmpty(publFilter))
            sqlDyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", publFilter);
        }
    else
        // old table schema, filter by doing a join on article table
        {
        if(isNotEmpty(yearFilter))
            sqlDyStringPrintfFrag(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \
                yearFilter);
        }


    if (extraDy->stringSize > 0)
        extra = extraDy->string;
    else
        extra = NULL;

    int rowOffset = 0;
    struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra,
                                               FALSE, NULL, &rowOffset);
    freeDyString(&extraDy);

    while ((row = sqlNextRow(sr)) != NULL)
	{
        struct bed *bed = bedLoad12(row+rowOffset);
        if (articleIds==NULL || hashFindVal(articleIds, bed->name))
            slAddHead(&lfList, bedMungToLinkedFeatures(&bed, tdb, 12, scoreMin, scoreMax, useItemRgb));
        }
    sqlFreeResult(&sr);
    slReverse(&lfList);
    slSort(&lfList, linkedFeaturesCmp);
    tg->items = lfList;
    }
hFreeConn(&conn);
}
Esempio n. 15
0
static struct pubsExtra *pubsMakeExtra(struct track* tg, char *articleTable, 
    struct sqlConnection* conn, struct linkedFeatures* lf)
/* bad solution: a function that is called before the extra field is 
 * accessed and that fills it from a sql query. Will need to redo this like gencode, 
 * drawing from atom, variome and bedLoadN or bedDetails */
{
char query[LARGEBUF];
struct sqlResult *sr = NULL;
char **row = NULL;
struct pubsExtra *extra = NULL;

if (sameWord(tg->table, "pubsBlat"))
    // legacy table format where bed-like table does not includ title but has to pull it out from 2nd table
    sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", 
        articleTable, lf->name);
else 
    // new table format
    sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s "
    "WHERE chrom = '%s' and chromStart = '%d' and name='%s'", tg->table, chromName, lf->start, lf->name);

sr = sqlGetResult(conn, query);
if ((row = sqlNextRow(sr)) != NULL)
    {
    char *firstAuthor = row[0];
    char *year    = row[1];
    char *title   = row[2];
    char *impact  = NULL;
    char *classes = NULL;


    extra = needMem(sizeof(struct pubsExtra));
    extra->label = pubsFeatureLabel(firstAuthor, year);
    if (isEmpty(title))
        extra->mouseOver = extra->label;
    else
        extra->mouseOver = cloneString(title);
    extra->color  = NULL;
    extra->shade  = -1;

    if (!sameWord(tg->table, "pubsBlat"))
        {
        impact  = row[3];
        classes = row[4];
        if (!isEmpty(impact)) 
            {
            char *colorBy = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsColorBy");
            if ((colorBy==NULL) || strcmp(colorBy,"topic")==0) 
                {
                char *classCopy = classes;
                char *mainClass = cloneNextWordByDelimiter(&classes, ',');
                classes = classCopy;
                if (mainClass!=NULL)
                    {
                    struct rgbColor *col = (struct rgbColor*) hashFindVal(pubsClassColors, mainClass);
                    extra->color = col;
                    // add class to mouseover text
                    struct dyString *mo = dyStringNew(0);
                    dyStringAppend(mo, extra->mouseOver);
                    dyStringAppend(mo, " (categories: ");
                    dyStringAppend(mo, classes);
                    dyStringAppend(mo, ")");
                    freeMem(extra->mouseOver);
                    extra->mouseOver = dyStringContents(mo);
                    }
                }
            else 
                {
                if (sameString(colorBy,"impact")) 
                    {
                    int impInt = atoi(impact);
                    if (impInt<=1)
                        extra->color = &impact1Color;
                    else if (impInt<=3)
                        extra->color = &impact2Color;
                    else if (impInt<=10)
                        extra->color = &impact3Color;
                    else
                        extra->color = &impact4Color;
                    
                    // add impact to mouseover text
                    struct dyString *mo = dyStringNew(0);
                    dyStringAppend(mo, extra->mouseOver);
                    dyStringAppend(mo, " (impact ");
                    dyStringAppend(mo, impact);
                    dyStringAppend(mo, ")");
                    freeMem(extra->mouseOver);
                    extra->mouseOver = dyStringContents(mo);
                    }

                if (sameString(colorBy,"year")) 
                    {
                    int relYear = (atoi(year)-1990); 
                    extra->shade = min(relYear/3, 10);
                    //extra->color = shadesOfGray[yearShade];
                    }
                }
            }
        }
    }


sqlFreeResult(&sr);
return extra;
}