src/hg/instinct/hgHeatmap2/hgHeatmap2.c 1.76
1.76 2009/06/04 03:50:37 jsanborn
added copyright notices, removed cluster library
Index: src/hg/instinct/hgHeatmap2/hgHeatmap2.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgHeatmap2/hgHeatmap2.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -b -B -U 1000000 -r1.75 -r1.76
--- src/hg/instinct/hgHeatmap2/hgHeatmap2.c 6 May 2009 00:06:35 -0000 1.75
+++ src/hg/instinct/hgHeatmap2/hgHeatmap2.c 4 Jun 2009 03:50:37 -0000 1.76
@@ -1,2376 +1,2380 @@
+/********************************************************************************/
+/* Copyright 2007-2009 -- The Regents of the University of California */
+/********************************************************************************/
+
/* hgHeatmap is a CGI script that produces a web page containing
* a graphic with all chromosomes in genome, and a heatmap or two
* on top of them. This module just contains the main routine,
* the routine that dispatches to various page handlers, and shared
* utility functions. */
#include "common.h"
#include "bed.h"
#include "cart.h"
#include "linefile.h"
#include "customTrack.h"
#include "genoLay.h"
#include "hash.h"
#include "hCommon.h"
#include "hdb.h"
#include "hgHeatmap2.h"
#include "hPrint.h"
#include "htmshell.h"
#include "hui.h"
#include "trackLayout.h"
#include "web.h"
#include "microarray.h"
#include "ra.h"
#include "hgStatsLib.h"
#include "featuresLib.h"
#include "json.h"
#include "hgHeatmapLib.h"
#include "heatmapUtility.h"
#include "hgUsers.h"
static char const rcsid[] = "$Id$";
/* ---- Global variables. ---- */
struct cart *cart; /* This holds cgi and other variables between clicks. */
struct hash *oldVars; /* Old cart hash. */
char *database; /* Name of the selected database - hg15, mm3, or the like. */
struct trackLayout tl; /* Dimensions of things, fonts, etc. */
struct slRef *ghList; /* List of active heatmaps */
struct hash *ghHash; /* Hash of active heatmaps */
struct geneSetGroup *gsList; /* List of available gene set groups */
struct hash *gsHash; /* Hash of available gene set groups */
struct geneSet *allGeneSets; /* List of current pathway collections */
char *theDataset=""; /* Name of the selected dataset */
char *ctFileName = NULL; /* Custom track file. */
struct customTrack *ctList = NULL; /* Custom tracks. */
boolean hasCustomTracks = FALSE; /* whether any custom tracks are for this db*/
struct slName *browserLines = NULL; /* Custom track "browser" lines. */
static char *heatMapDbProfile = "localDb"; // database profile to use
struct chromZoom {
struct chromZoom *next;
char *fullName;
int size;
int baseStart;
int baseEnd;
};
void usage()
/* Explain usage and exit. */
{
errAbort(
"hgHeatmap2 - Full genome (as opposed to chromosome) view of data\n"
"This is a cgi script, but it takes the following parameters:\n"
" db=<genome database>\n"
" hght_table=on where table is name of bed table\n"
);
}
/******************* BEGIN helper routines ***************************/
char *cartSettingsString(char *prefix, char *functionName)
{
if (!prefix || !functionName)
return NULL;
struct hashEl *hEl = cartFindPrefix(cart, prefix);
if (!hEl)
return NULL;
struct dyString *dy = newDyString(1000);
while (hEl)
{
char *name = hEl->name;
char *val = hEl->val;
dyStringPrintf(dy, "%s=%s,", name, val);
hEl = hEl->next;
}
dyStringPrintf(dy, "%s,%s", functionName, VERSION);
return dy->string;
}
int experimentHeight()
/* Return height of an individual experiment */
{
return 1;
}
char *dataSetRaName()
{
return "datasets.ra";
}
int heatmapHeight(struct genoHeatmap *gh)
/* Return height of the heatmap. */
{
if (gh == NULL)
return 0;
if (sameWord(gh->dataType,"bed 15"))
return slCount(gh->sampleList) * experimentHeight();
return gh->height;
}
struct column *dataSetsCols()
{
char *raName_data = dataSetRaName();
struct column *colList = getColumns(NULL, raName_data, NULL);
return colList;
}
struct rgbColor *parseRGBString(char *str)
{ /* parses a comma-separated list of colors, returns a rgbColor */
if (!str)
return NULL;
struct slName *sl, *slList = slNameListFromComma(str);
if (slCount(slList) != 3)
return NULL;
sl = slList;
if (!isdigit(sl->name[0]))
return NULL;
int r = atoi(sl->name);
if (r < 0 || r > 255)
return NULL;
sl = sl->next;
if (!isdigit(sl->name[0]))
return NULL;
int g = atoi(sl->name);
if (g < 0 || g > 255)
return NULL;
sl = sl->next;
if (!isdigit(sl->name[0]))
return NULL;
int b = atoi(sl->name);
if (b < 0 || b > 255)
return NULL;
struct rgbColor *rgb = NULL;
AllocVar(rgb);
rgb->r = r;
rgb->g = g;
rgb->b = b;
return rgb;
}
void setUserDefinedColor(struct heatmapLay *hl)
{
if (!hl)
return;
char *lowColor = cartOptionalString(cart, hgh2LowColor);
char *zeroColor = cartOptionalString(cart, hgh2ZeroColor);
char *highColor = cartOptionalString(cart, hgh2HighColor);
struct rgbColor *low = parseRGBString(lowColor);
struct rgbColor *zero = parseRGBString(zeroColor);
struct rgbColor *high = parseRGBString(highColor);
if (!low || !zero || !high)
return;
hl->lowColor = low;
hl->zeroColor = zero;
hl->highColor = high;
}
void parseChromString(char *chromStr, char **chrom, int *base)
{
if (!chromStr)
return;
chromStr = replaceChars(chromStr, ",", "");
if (sameString(chromStr, "undefined"))
return;
struct slName *slList = slNameListFromString(chromStr, ':');
if (slCount(slList) == 1)
{
char *str = slList->name;
if (isdigit(str[0]))
*base = atoi(str);
else
*chrom = cloneString(str);
}
else if (slCount(slList) == 2)
{
struct slName *sl = slList;
*chrom = cloneString(sl->name);
sl = sl->next;
*base = atoi(sl->name);
}
else
errAbort("Got wrong slCount(chromStr)");
}
void parseChromStrings(char *startStr, char **startChrom, int *startBase,
char *stopStr, char **stopChrom, int *stopBase)
{
parseChromString(startStr, startChrom, startBase);
parseChromString(stopStr, stopChrom, stopBase);
/* To conform to regular genome browser search, assume constrained to sane
* chrom when one chrom string is ommited */
if ((*startChrom != NULL) && (*stopChrom == NULL))
*stopChrom = cloneString(*startChrom);
if ((*startChrom == NULL) && (*stopChrom != NULL))
*stopChrom = cloneString(*startChrom);
}
void setupFeaturePriority(struct genoHeatmap *gh, char *featureList)
{
if (!gh)
return;
struct sqlConnection *conn = getFeatureDbConn(gh);
if (!conn)
return;
char *raName = gh->raFile;
struct column *col, *colList = getColumns(conn, raName, gh->patDb);
hFreeConn(&conn);
struct slName *features = slNameListFromComma(featureList);
int i, notPriority = slCount(features);
struct dyString *priorities = newDyString(1000);
for (col = colList; col; col = col->next)
{
if ((i = slNameFindIx(features, col->name)) != -1)
dyStringPrintf(priorities, "%s %d ", col->name, i);
else
{
dyStringPrintf(priorities, "%s %d ", col->name, notPriority);
notPriority++;
}
}
char varName[256];
safef(varName, sizeof(varName),"%s.%s", colOrderVar, gh->patDb);
cartSetString(cart, varName, priorities->string);
}
void setupFeatureVisibility(struct genoHeatmap *gh)
{
if (!gh)
return;
if (!sameWord(gh->dataType, "bed 15"))
return;
char *featureList = cartOptionalString(cart, hgh2FeatureList);
if (!featureList)
return;
struct sqlConnection *conn = getFeatureDbConn(gh);
if (!conn)
return;
char *raName = gh->raFile;
struct column *col, *colList = getColumns(conn, raName, gh->patDb);
hFreeConn(&conn);
struct slName *features = slNameListFromComma(featureList);
int i;
for (col = colList; col; col = col->next)
{
char varName[256];
safef(varName, sizeof(varName), "%s%s.vis", colConfigPrefix, col->name);
if ((i = slNameFindIx(features, col->name)) != -1)
cartSetString(cart, varName, "1");
else
cartSetString(cart, varName, "0");
}
setupFeaturePriority(gh, featureList);
}
void setupSortByFeature(struct genoHeatmap *gh)
{
char *featureSort = cartOptionalString(cart, hgh2FeatureSort);
char *featureSortDir = cartOptionalString(cart, hgh2FeatureSortDir);
if (!featureSort || !featureSortDir)
return;
struct slName *f, *features = slNameListFromComma(featureSort);
struct slName *d, *directions = slNameListFromComma(featureSortDir);
if (slCount(features) != slCount(directions))
return;
f = features;
d = directions;
int i;
for (i = 0; i < slCount(features); i++)
{
char varName[256];
safef(varName, sizeof(varName), "%s.%s.%s.%s", colConfigPrefix,
f->name, "sortType", gh->patDb);
if (sameString(d->name, "DESC"))
cartSetString(cart, varName, "descending");
else if (sameString(d->name, "ASC"))
cartSetString(cart, varName, "ascending");
f = f->next;
d = d->next;
}
}
struct slName *setupSortByChromPosition(struct genoHeatmap *gh)
{
char *chromStart = cartOptionalString(cart, hgh2SortChromStart);
char *chromEnd = cartOptionalString(cart, hgh2SortChromEnd);
if (!chromStart || !chromEnd)
return NULL;
int direction = 1;
char *sortDir = cartOptionalString(cart, hgh2SortDir);
if (!sortDir)
direction = 1;
else if (sameString(sortDir, "ASC"))
direction = 1;
else if (sameString(sortDir, "DESC"))
direction = -1;
char *startChrom = NULL;
int startBase = -1;
char *stopChrom = NULL;
int stopBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &stopChrom, &stopBase);
stopBase += 1; // to fix a drawing issue.
if (!startChrom || !stopChrom)
return NULL;
if (!sameString(startChrom, stopChrom))
return NULL; // let's force sorting to data on same chromosome.
return samplesSortedByChromPos(gh, startChrom, startBase, stopBase, direction);
}
struct slName *setupSortByGene(struct genoHeatmap *gh)
{
char *sortGene = cartOptionalString(cart, hgh2SortGene);
if (!sortGene)
return NULL;
int direction = 1;
char *sortDir = cartOptionalString(cart, hgh2SortDir);
if (!sortDir)
direction = 1;
else if (sameString(sortDir, "ASC"))
direction = 1;
else if (sameString(sortDir, "DESC"))
direction = -1;
return samplesSortedByGene(gh, sortGene, direction);
}
void setupSort(struct genoHeatmap *gh)
{
if (!gh)
return;
if (!sameWord(gh->dataType, "bed 15"))
return;
char *sortType = cartOptionalString(cart, hgh2SortType);
if (!sortType)
{
defaultOrder(gh);
return;
}
if (sameString(sortType, "feature"))
{
setupSortByFeature(gh);
sortPersonOrder(gh);
}
else if (sameString(sortType, "chrom"))
{
struct slName *sortList = setupSortByChromPosition(gh);
setSampleOrder(gh, sortList);
}
else if (sameString(sortType, "gene"))
{
struct slName *sortList = setupSortByGene(gh);
setSampleOrder(gh, sortList);
}
else
defaultOrder(gh); // make sure gh->sampleOrder is set to default.
}
void setupMinMaxSubgroupCartVars(struct genoHeatmap *gh, struct slName *features,
struct slName *mins, struct slName *maxs, int subsetNum)
{
int i = 0;
struct slName *f = features;
struct slName *mn = mins;
struct slName *mx = maxs;
for (i = 0; i < slCount(features); i++)
{
char minName[128];
safef(minName, sizeof(minName), "%s.%s.%s.%s.%d",
advFilterPrefix, f->name, "min", gh->patDb, subsetNum);
char maxName[128];
safef(maxName, sizeof(maxName), "%s.%s.%s.%s.%d",
advFilterPrefix, f->name, "max", gh->patDb, subsetNum);
cartSetString(cart, minName, mn->name);
cartSetString(cart, maxName, mx->name);
f = f->next;
mn = mn->next;
mx = mx->next;
}
}
void setMinMaxSubgroups(struct genoHeatmap *gh)
{
char *subgroup1Features = cartOptionalString(cart, hgh2Subgroup1Features);
char *subgroup2Features = cartOptionalString(cart, hgh2Subgroup2Features);
if (!subgroup1Features || !subgroup2Features)
return;
char *subgroup1Mins = cartOptionalString(cart, hgh2Subgroup1Mins);
char *subgroup1Maxs = cartOptionalString(cart, hgh2Subgroup1Maxs);
char *subgroup2Mins = cartOptionalString(cart, hgh2Subgroup2Mins);
char *subgroup2Maxs = cartOptionalString(cart, hgh2Subgroup2Maxs);
if (!subgroup1Mins || !subgroup1Maxs
|| !subgroup2Mins || !subgroup2Maxs )
return;
struct slName *features1 = slNameListFromComma(subgroup1Features);
struct slName *features2 = slNameListFromComma(subgroup2Features);
struct slName *mins1 = slNameListFromComma(subgroup1Mins);
struct slName *maxs1 = slNameListFromComma(subgroup1Maxs);
struct slName *mins2 = slNameListFromComma(subgroup2Mins);
struct slName *maxs2 = slNameListFromComma(subgroup2Maxs);
if (slCount(features1) != slCount(features2))
return;
if (slCount(mins1) != slCount(maxs1))
return;
if (slCount(mins2) != slCount(maxs2))
return;
if ((slCount(features1) != slCount(mins1)) || (slCount(features1) != slCount(mins2)))
return;
setupMinMaxSubgroupCartVars(gh, features1, mins1, maxs1, 0);
setupMinMaxSubgroupCartVars(gh, features2, mins2, maxs2, 1);
}
void setupCodedSubgroupCartVars(struct genoHeatmap *gh, struct slName *features,
struct slName *codes, int subsetNum)
{
int i = 0;
struct slName *ft = features;
struct slName *cd = codes;
struct hash *codeHash = hashNew(0);
for (i = 0; i < slCount(features); i++)
{
hashAdd(codeHash, ft->name, cd->name);
ft = ft->next;
cd = cd->next;
}
char *name;
struct hashCookie hc = hashFirst(codeHash);
while ((name = hashNextName(&hc)) != NULL)
{
char code[128];
safef(code, sizeof(code), "%s.%s.%s.%s.%d",
advFilterPrefix, name, "codes", gh->patDb, subsetNum);
struct dyString *dy = dyStringNew(100);
struct hashEl *el = hashLookup(codeHash, name);
while (el)
{
char *codedVal = el->val;
dyStringPrintf(dy, "%s", codedVal);
if (el->next)
dyStringPrintf(dy, ",");
el = el->next;
}
cartSetString(cart, code, dy->string);
dyStringFree(&dy);
}
}
void setCodedSubgroup(struct genoHeatmap *gh, char *features, char *codes, int subset)
{
if (!features || !codes)
return;
struct slName *slFeatures = slNameListFromComma(features);
struct slName *slCodes = slNameListFromComma(codes);
if (!slFeatures || !slCodes)
return;
if (slCount(slFeatures) != slCount(slCodes))
return;
setupCodedSubgroupCartVars(gh, slFeatures, slCodes, subset);
}
void setCodedSubgroups(struct genoHeatmap *gh)
{
char *subgroup1Features = cartOptionalString(cart, hgh2Subgroup1CodedFeatures);
char *subgroup1Codes = cartOptionalString(cart, hgh2Subgroup1Codes);
setCodedSubgroup(gh, subgroup1Features, subgroup1Codes, 0);
char *subgroup2Features = cartOptionalString(cart, hgh2Subgroup2CodedFeatures);
char *subgroup2Codes = cartOptionalString(cart, hgh2Subgroup2Codes);
setCodedSubgroup(gh, subgroup2Features, subgroup2Codes, 1);
}
void setSubgroups(struct genoHeatmap *gh)
{
setMinMaxSubgroups(gh);
setCodedSubgroups(gh);
}
void addCustomDbHeatmaps(struct genoHeatmap **list, char *raName)
{
struct customTrack *ct = NULL;
ctList = customTracksParseCart(database, cart, NULL, NULL);
if(!ctList)
return;
struct genoHeatmap *gh;
for(ct = ctList; ct != NULL; ct = ct->next)
{
gh = getCustomHeatmap(ct);
if (!gh)
continue;
slAddHead(list, gh);
}
}
void addUserDbHeatmaps(struct genoHeatmap **list, char *raName)
{
/* only to test user authentication currently */
char *tokenIdStr = cartOptionalString(cart, hgh2UserTokenId);
char *userIdStr = cartOptionalString(cart, hgh2UserId);
if (!tokenIdStr || !userIdStr)
return;
int tokenId = atoi(tokenIdStr);
int userId = atoi(userIdStr);
struct slName *sl, *datasets = getUserDatasets(cart, tokenId, userId);
if (!datasets)
return;
if (!slCount(datasets))
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
if (!conn)
return;
char *name;
struct genoHeatmap *gh;
struct column *colList = getColumns(NULL, raName, NULL);
struct column *col;
if (!colList)
return;
for (col = colList; col != NULL; col = col->next)
{
name = (char *)(hashFindVal(col->settings, "name"));
boolean userHasAccess = FALSE;
for (sl = datasets; sl; sl = sl->next)
if (sameString(sl->name, name))
userHasAccess = TRUE;
if (!userHasAccess)
continue;
gh = getHeatmap(conn, database, name, col->settings);
if (!gh)
continue;
if (!gh->private)
continue; // do not public private datasets.
slAddHead(list, gh);
}
hFreeConn(&conn);
}
struct genoHeatmap *getUserDbHeatmaps(char *raName)
/* Get graphs defined. Requried to be present in the database as well as
in the datasets.ra file */
{
struct genoHeatmap *list = NULL;
addUserDbHeatmaps(&list, raName);
return list;
}
struct genoHeatmap *getDbHeatmaps(char *set, char *raName)
/* Get graphs defined. Requried to be present in the database as well as
in the datasets.ra file */
{
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
if (!conn)
return NULL;
char varName[1024];
char *name;
struct genoHeatmap *list = NULL, *gh;
struct column *colList = getColumns(NULL, raName, NULL);
struct column *col;
if (colList == NULL)
errAbort("Couldn't find anything from %s", raName);
for (col = colList; col != NULL; col = col->next)
{
name = (char *)(hashFindVal(col->settings, "name"));
safef(varName, sizeof(varName), "%s%s.%s", hghDataConfigPrefix, name, hghVis);
/* cgi visibility */
char *vis;
if (!hashLookup(cart->hash,varName))
/* default visibility */
vis = (char *)(hashFindVal(col->settings, "visibility"));
else
{
boolean cgiVis = cartBoolean(cart,varName);
if (cgiVis)
vis = "on";
else
vis = "off";
}
gh = getHeatmap(conn, database, name, col->settings);
if (!gh)
continue;
if (gh->private)
continue; // do not include private datasets.
slAddHead(&list,gh);
}
hFreeConn(&conn);
addUserDbHeatmaps(&list, raName);
addCustomDbHeatmaps(&list, raName);
slReverse(&list);
return list;
}
void getGenoHeatmaps(char* set)
/* Set up ghList and ghHash with all available genome graphs */
{
if (isEmpty(set))
return;
char *datasetRaName = dataSetRaName();
struct genoHeatmap *dbList = getDbHeatmaps(set, datasetRaName);
struct genoHeatmap *gh;
struct slRef *ref, *refList = NULL;
/* Build up ghList from user and db lists. */
for (gh = dbList; gh != NULL; gh = gh->next)
refAdd(&refList, gh);
slReverse(&refList);
ghList = refList;
/* Build up ghHash from ghList. */
ghHash = hashNew(0);
for (ref = ghList; ref != NULL; ref = ref->next)
{
gh = ref->val;
hashAdd(ghHash, gh->name, gh);
}
}
void getStatsFxn(char *statsFxn, boolean (**func)(float data1[], unsigned long n1,
float data2[], unsigned long n2,
float *r, float *prob), float *colorCutoff)
{
/* get statistical function setting */
if (sameWord(statsFxn,"diffMean"))
{
*func = aveDiff;
// no gray color colorCutoff
*colorCutoff = 0;
}
else if (sameWord(statsFxn,"ttest"))
{
*func = ttest;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"wilcoxon"))
{
*func = wilcoxon;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"expressionCoherence"))
{
*func = expressionCoherence;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"fishersExact"))
{
*func = fishersExact;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"fishersLinearDisc"))
{
*func = fishersLinearDisc;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"jarqueBera"))
{
*func = jarqueBera;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"levene"))
{
*func = levene;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
else if (sameWord(statsFxn,"brownForsythe"))
{
*func = brownForsythe;
// this colorCutoff is equivalent of p<0.05 in -log10(p)
*colorCutoff = hghProbCutoff;
}
}
/******************* END helper routines ***************************/
/************* JSON Return strings *********************************/
void jsonFeatureList(struct json *js, struct genoHeatmap *gh)
/* JSON return string for feature panel */
{
struct json *new, *list = jsonAddContainerList(js, "features");
new = list;
struct sqlConnection *conn = getFeatureDbConn(gh);
if (!conn)
return;
char *raName = gh->raFile;
struct column *col, *colList = getColumns(conn, raName, gh->patDb);
for (col = colList; col != NULL; col = col->next)
{
jsonAddString(new, "name", col->name);
jsonAddString(new, "shortLabel", col->shortLabel);
jsonAddString(new, "longLabel", col->longLabel);
if (col->cellCoded(col, conn))
{
struct slName *slList = col->cellCodedVals(col, conn);
jsonAddSlName(new, "codes", slList);
}
else
{
char *minValStr = col->cellMinVal(col, conn);
double minVal, maxVal;
if (!minValStr)
minVal = 0.0;
else
minVal = atof(minValStr);
char *maxValStr = col->cellMaxVal(col, conn);
if (!maxValStr)
maxVal = 0.0;
else
maxVal = atof(maxValStr);
jsonAddDouble(new, "minVal", minVal);
jsonAddDouble(new, "maxVal", maxVal);
}
if (col->next)
new = jsonAddContainerToList(&list);
}
hFreeConn(&conn);
}
void jsonChromHeatmapLay(struct json *js, struct heatmapLay *hl)
/* JSON return string for chromosome layout info */
{
if (!hl)
return;
jsonAddInt(js, "sampleHeight", hl->sampleHeight);
struct json *new, *list = jsonAddContainerList(js, hl->name);
new = list;
struct hmElement *hEl;
for (hEl = hl->elements; hEl; hEl = hEl->next)
{
jsonAddString(new, "chromNum", hEl->name+3);
jsonAddInt(new, "pixelStart", hEl->pixelStart);
jsonAddInt(new, "pixelEnd", hEl->pixelEnd);
jsonAddInt(new, "baseStart", hEl->baseStart); // make this and below %lu
jsonAddInt(new, "baseEnd", hEl->baseEnd);
if (hEl->next)
new = jsonAddContainerToList(&list);
}
}
void jsonGenesetLayout(struct json *js, struct heatmapLay *hlList)
/* JSON return string for geneset layout info */
{
if (!hlList)
return;
jsonAddInt(js, "sampleHeight", hlList->sampleHeight);
struct json *set, *setList = jsonAddContainerList(js, "geneSetInfo");
set = setList;
struct heatmapLay *hl;
for (hl = hlList; hl; hl = hl->next)
{
jsonAddString(set, "name", hl->name);
jsonAddInt(set, "pixelStart", hl->pixelStart);
jsonAddInt(set, "pixelEnd", hl->pixelEnd);
struct json *gene, *geneList = jsonAddContainerList(set, "geneInfo");
gene = geneList;
struct hmElement *hEl;
for (hEl = hl->elements; hEl; hEl = hEl->next)
{
jsonAddString(gene, "probeName", hEl->probeName);
jsonAddString(gene, "geneName", hEl->name);
jsonAddInt(gene, "pixelStart", hEl->pixelStart);
jsonAddInt(gene, "pixelEnd", hEl->pixelEnd);
if (hEl->next)
gene = jsonAddContainerToList(&geneList);
}
if (hl->next)
set = jsonAddContainerToList(&setList);
}
}
void jsonFeatureHeatmapLay(struct json *js, struct heatmapLay *hl)
/* JSON return string for feature panel layout info */
{
if (!hl)
return;
jsonAddInt(js, "sampleHeight", hl->sampleHeight);
struct json *new, *list = jsonAddContainerList(js, hl->name);
new = list;
struct hmElement *hEl;
for (hEl = hl->elements; hEl; hEl = hEl->next)
{
jsonAddString(new, "name", hEl->name);
jsonAddInt(new, "pixelStart", hEl->pixelStart);
jsonAddInt(new, "pixelEnd", hEl->pixelEnd);
if (hEl->next)
new = jsonAddContainerToList(&list);
}
}
void jsonSampleList(struct json *js, struct genoHeatmap *gh)
/* JSON return string for sample list */
{
if (!gh)
return;
jsonAddSlName(js, "samples", gh->sampleList);
}
/********************** END JSON *******************************/
void adjustStats(struct genoHeatmap *gh)
{
if (!gh)
return;
char *correction = cartOptionalString(cart, hgh2StatsCorrection);
if (!correction)
return;
if (sameString(correction, "bonferroni"))
adjustBonferroni(gh);
else if (sameString(correction, "fdr"))
return;
}
/********************** Begin Drawing dispatchers **************/
void drawGenomeStats(struct genoHeatmap *gh, char *statsFxn, char *chromStart,
char *chromEnd, int subsetNum, int width, int sampleHeight,
char **statsGif, char **scaleGif)
{
boolean (*func)(float data1[], unsigned long n1, float data2[],
unsigned long n2, float *r, float *prob) = NULL;
float colorCutoff = 0.0;
getStatsFxn(statsFxn, &func, &colorCutoff);
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = chromLayout(conn, gh, startChrom, startBase,
endChrom, endBase, width, sampleHeight);
if (differentWord(gh->dataType,"bed 15") || !gotAdvFilter(gh->patDb) || !func)
return;
//get the analysis results
char *raName= gh->raFile;
boolean useAccessTable = TRUE;
char *chromName = NULL;
if (startChrom && endChrom)
if (sameString(startChrom, endChrom))
{
useAccessTable = FALSE;
chromName = startChrom;
}
gh->anaResult = diffAveSubgroup(gh, subsetNum, raName, func, chromName, useAccessTable);
adjustStats(gh);
char *filename = genomeStatsGif(conn, hl, gh, colorCutoff);
if (filename)
*statsGif = cloneString(filename);
filename = simpleScaleGif(hl, gh, 1, 1);
if (filename)
*scaleGif = cloneString(filename);
hFreeConn(&conn);
}
void drawGenesetStats(struct genoHeatmap *gh, char *statsFxn, char *geneSetNames,
char *userGeneset, int subsetNum, int width, int sampleHeight,
char **statsGif, char **scaleGif)
{
if (!geneSetNames)
return;
boolean (*func)(float data1[], unsigned long n1, float data2[],
unsigned long n2, float *r, float *prob) = NULL;
float colorCutoff = 0.0;
getStatsFxn(statsFxn, &func, &colorCutoff);
if (differentWord(gh->dataType, "bed 15") || !gotAdvFilter(gh->patDb) || !func)
return;
//get the analysis results
char *raName= gh->raFile;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = genesetLayout(gh, geneSetNames, width, sampleHeight);
if (!hl)
return;
struct geneSet *geneSets = getAllPathways(cart, getPathwayDb(), geneSetNames);
gh->anaResultHash = diffSubgroupHash(gh, subsetNum, raName, geneSets, NULL, func);
adjustStats(gh);
char *filename = genesetStatsGif(conn, hl, gh, colorCutoff);
if (filename)
*statsGif = cloneString(filename);
filename = simpleScaleGif(hl, gh, 1, 1);
if (filename)
*scaleGif = cloneString(filename);
hFreeConn(&conn);
}
void drawGenomeSummary(struct json *js, struct genoHeatmap *gh, char *chromStart,
char *chromEnd, int width, int sampleHeight)
{
if (!gh)
return;
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = chromLayout(conn, gh, startChrom, startBase,
endChrom, endBase, width, sampleHeight);
setUserDefinedColor(hl);
char *raName = gh->raFile;
int subsetNum = cartUsualInt(cart, hgh2SubgroupNum, hgh2SubgroupDefaultNum);
jsonChromHeatmapLay(js, hl);
int totalHeight = heatmapHeight(gh) * hl->sampleHeight;
/* This is the key function to call for subgrouping */
struct slName **ptSubsets = NULL;
int ifSubsets = getSubsetsIfAny(gh, subsetNum, raName, &ptSubsets);
if (!ifSubsets)
{
char *gGif = genomeSummaryGif(conn, hl, gh, gh->sampleList, totalHeight, 1, 1);
jsonAddString(js, "heatmap", gGif);
char *sGif = simpleScaleGif(hl, gh, 1, 1);
jsonAddString(js, "scale", sGif);
}
else
{
if (!ptSubsets)
errAbort("ptSubsets == NULL");
int i;
int height = 0;
for (i = 0; i < subsetNum; i++)
{
if (!ptSubsets[i])
errAbort("ptSubsets[%d] == NULL", i);
height += slCount(ptSubsets[i]) * hl->sampleHeight;
}
if (height < totalHeight)
height = totalHeight;
height /= subsetNum;
for (i = 0; i < subsetNum; i++)
{
heatmapLayResetMinMax(hl);
char *gGif = genomeSummaryGif(conn, hl, gh, ptSubsets[i], height, i, subsetNum);
char heatStr[128];
safef(heatStr, sizeof(heatStr), "heatmap%d", i+1);
jsonAddString(js, heatStr, gGif);
char *sGif = simpleScaleGif(hl, gh, i, subsetNum);
char scaleStr[128];
safef(scaleStr, sizeof(scaleStr), "scale%d", i+1);
jsonAddString(js, scaleStr, sGif);
}
}
hFreeConn(&conn);
}
void drawGenesetSummary(struct json *js, struct genoHeatmap *gh, char *geneSetNames,
char *userGeneset, int width, int height)
{
if (!gh || !geneSetNames)
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = genesetLayout(gh, geneSetNames, width, height);
if (!hl)
return;
setUserDefinedColor(hl);
jsonGenesetLayout(js, hl);
char *raName = gh->raFile;
int subsetNum = cartUsualInt(cart, hgh2SubgroupNum, hgh2SubgroupDefaultNum);
struct slName **ptSubsets = NULL;
int ifSubsets = getSubsetsIfAny(gh, subsetNum, raName, &ptSubsets);
int totalHeight = heatmapHeight(gh) * hl->sampleHeight;
if (!ifSubsets)
{
char *gGif = genesetSummaryGif(conn, hl, gh, gh->sampleList, totalHeight, 1, 1);
jsonAddString(js, "heatmap", gGif);
char *sGif = simpleScaleGif(hl, gh, 1, 1);
jsonAddString(js, "scale", sGif);
}
else
{
if (!ptSubsets)
errAbort("ptSubsets == NULL");
int i;
int height = 0;
for (i = 0; i < subsetNum; i++)
{
if (!ptSubsets[i])
errAbort("ptSubsets[%d] == NULL", i);
height += slCount(ptSubsets[i]) * hl->sampleHeight;
}
if (height < totalHeight)
height = totalHeight;
height /= 2;
for (i = 0; i < subsetNum; i++)
{
heatmapLayResetMinMax(hl);
char *gGif = genesetSummaryGif(conn, hl, gh, ptSubsets[i], height, i, subsetNum);
char heatStr[128];
safef(heatStr, sizeof(heatStr), "heatmap%d", i+1);
jsonAddString(js, heatStr, gGif);
char *sGif = simpleScaleGif(hl, gh, i, subsetNum);
char scaleStr[128];
safef(scaleStr, sizeof(scaleStr), "scale%d", i+1);
jsonAddString(js, scaleStr, sGif);
}
}
hFreeConn(&conn);
}
void drawGenomeHeatmap(struct json *js, struct genoHeatmap *gh, char *chromStart,
char *chromEnd, int width, int sampleHeight)
{
if (!gh)
return;
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = chromLayout(conn, gh, startChrom, startBase,
endChrom, endBase, width, sampleHeight);
setUserDefinedColor(hl);
char *gGif = genomeGif(conn, hl, gh);
jsonAddString(js, "heatmap", gGif);
jsonChromHeatmapLay(js, hl);
hFreeConn(&conn);
}
void drawGenomeLabels(struct json *js, char *chromStart, char *chromEnd, int width)
{
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
struct heatmapLay *hl = chromLayout(conn, NULL, startChrom, startBase,
endChrom, endBase, width, 1);
char *gGif = genomeLabelsGif(conn, hl);
jsonAddString(js, "labels", gGif);
jsonChromHeatmapLay(js, hl);
hFreeConn(&conn);
}
void drawGenesetHeatmap(struct json *js, struct genoHeatmap *gh, char *geneSetNames,
char *userGeneset, int width, int sampleHeight)
{
if (!gh || !geneSetNames)
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = genesetLayout(gh, geneSetNames, width, sampleHeight);
if (!hl)
return;
setUserDefinedColor(hl);
char *gGif = genesetGif(conn, hl, gh);
jsonAddString(js, "heatmap", gGif);
jsonGenesetLayout(js, hl);
hFreeConn(&conn);
}
void drawGenesetsLabels(struct json *js, char *geneSetNames, char *userGeneset, int width)
{
if (!geneSetNames)
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
struct heatmapLay *hl = genesetLayout(NULL, geneSetNames, width, 1);
if (!hl)
return;
char *gGif = genesetLabelsGif(conn, hl);
jsonAddString(js, "labels", gGif);
jsonGenesetLayout(js, hl);
hFreeConn(&conn);
}
void drawAnnotation(struct json *js, char *table, char *chromStart, char *chromEnd, int width)
{
if (!table)
return;
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
int sampleHeight = 0;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
struct heatmapLay *hl = chromLayout(conn, NULL, startChrom, startBase,
endChrom, endBase, width, sampleHeight);
hFreeConn(&conn);
char *aGif = annotationGif(hl, table);
jsonAddString(js, "annotation", aGif);
jsonChromHeatmapLay(js, hl);
}
void drawFeatureHeatmap(struct json *js, struct genoHeatmap *gh, int width, int sampleHeight)
{
if (!gh)
return;
if (!gh->patDb)
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = featureLayout(gh, width, sampleHeight);
char *fGif = featureGif(conn, hl, gh, gh->name);
struct slName *sl;
if (fGif)
sl = slNameNew(fGif);
else
sl = slNameNew("");
jsonAddSlName(js, "feature", sl);
jsonFeatureHeatmapLay(js, hl);
hFreeConn(&conn);
}
void addPixelOffsetHeatmapLay(struct heatmapLay *hl, int pixOffset)
{
if (!hl)
return;
struct hmElement *hEl;
for (hEl = hl->elements; hEl; hEl = hEl->next)
{
hEl->pixelStart = hEl->pixelStart + pixOffset;
hEl->pixelEnd = hEl->pixelEnd + pixOffset;
}
hl->width = hl->width + pixOffset;
}
void drawFeatureSummaryHeatmap(struct json *js, struct genoHeatmap *gh,
int width, int sampleHeight)
{
if (!gh)
return;
if (!gh->patDb)
return;
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, gh->database);
struct heatmapLay *hl = featureLayout(gh, width, sampleHeight);
char *raName = gh->raFile;
int subsetNum = cartUsualInt(cart, hgh2SubgroupNum, hgh2SubgroupDefaultNum);
/* This is the key function to call for subgrouping */
struct slName **ptSubsets = NULL;
int ifSubsets = getSubsetsIfAny(gh, subsetNum, raName, &ptSubsets);
if (!ifSubsets)
{
int buffer = 0;
char *fGif = featureSummaryGif(conn, hl, gh, gh->name,
gh->sampleList, buffer, 0, 1);
struct slName *sl;
if (fGif)
sl = slNameNew(fGif);
else
sl = slNameNew("");
jsonAddSlName(js, "feature", sl);
}
else
{
if (!ptSubsets)
errAbort("ptSubsets == NULL");
int i, buffer = slCount(gh->sampleList) * hl->sampleHeight;
for (i = 0; i < subsetNum; i++)
buffer -= slCount(ptSubsets[i]) * hl->sampleHeight;
if (buffer <= 0)
buffer = 1;
addPixelOffsetHeatmapLay(hl, hghSubgroupDefaultPixWidth + 3); // add 3 pixel buffer
for (i = 0; i < subsetNum; i++)
{
char *fGif = featureSummaryGif(conn, hl, gh, gh->name,
ptSubsets[i], buffer, i, subsetNum);
struct slName *sl;
if (fGif)
sl = slNameNew(fGif);
else
sl = slNameNew("");
char heatStr[128];
safef(heatStr, sizeof(heatStr), "feature%d", i);
jsonAddSlName(js, heatStr, sl);
}
}
jsonFeatureHeatmapLay(js, hl);
hFreeConn(&conn);
}
int datasetCmpShortLabel(const void *va, const void *vb)
/* Compare to sort columns based on priority. */
{
const struct dataset *a = *((struct dataset **)va);
const struct dataset *b = *((struct dataset **)vb);
return strcasecmp(a->shortLabel, b->shortLabel);
}
struct datasetGroup *datasetGroupFind(struct datasetGroup *list, char *string)
/* Return first element of slName list (or any other list starting
* with next/name fields) that matches string. */
{
struct datasetGroup *el;
for (el = list; el != NULL; el = el->next)
if (sameWord(string, el->name))
return el;
return NULL;
}
/********************** END Drawing dispatchers **************/
/********************** BEGIN hgHeatmap2 Modes ********************/
void modeLoad()
{
char *key = cartOptionalString(cart, hgh2Key);
char *settings = retrieveSettings(cart, key);
if (settings)
hPrintf("%s", settings);
else
hPrintf("({ })");
}
void modeSave()
{
char *vars = cartOptionalString(cart, hgh2Vars);
if (!vars)
return;
int key = saveUserSettings(cart, vars);
struct json *js = newJson();
char keyStr[128];
if (key >= 0)
safef(keyStr, sizeof(keyStr), "%d", key);
else
safef(keyStr, sizeof(keyStr), "n/a");
jsonAddString(js, "key", keyStr);
hPrintf("%s", js->print(js));
}
void modeGetUserDatasets()
{
struct genoHeatmap *gh;
struct dataset *da;
struct datasetGroup *gr, *groups = NULL;
char *datasetRaName = dataSetRaName();
/* Get all private access datasets user has access to */
struct genoHeatmap *userGhList = getUserDbHeatmaps(datasetRaName);
if (!userGhList)
jsonWarnAbort("No private datasets available to user");
for (gh = userGhList; gh; gh = gh->next)
{
char *group = gh->group;
if (!group)
group = "User Datasets"; // default name.
gr = datasetGroupFind(groups, group); // For some reason, slNameFind(...) doesn't work.
if (!gr)
{
AllocVar(gr);
gr->name = cloneString(group);
gr->datasets = NULL;
slAddHead(&groups, gr);
}
AllocVar(da);
da->name = cloneString(gh->name);
da->shortLabel = cloneString(gh->shortLabel);
da->longLabel = cloneString(gh->longLabel);
da->url = cloneString(gh->url);
da->expCount = gh->expCount;
slAddHead(&gr->datasets, da);
}
slReverse(&groups);
struct json *js = newJson();
for (gr = groups; gr; gr = gr->next)
{
slSort(&gr->datasets, datasetCmpShortLabel);
struct json *set, *group = jsonAddContainerList(js, gr->name);
set = group;
for (da = gr->datasets; da; da = da->next)
{
jsonAddString(set, "name", da->name);
jsonAddString(set, "shortLabel", da->shortLabel);
jsonAddString(set, "longLabel", da->longLabel);
jsonAddString(set, "url", da->url);
jsonAddInt(set, "N", da->expCount);
if (da->next)
set = jsonAddContainerToList(&group);
}
}
hPrintf("%s", js->print(js));
}
void modeLogin()
{
char *login = cartOptionalString(cart, hgh2UserLogin);
char *pass = cartOptionalString(cart, hgh2UserPass);
char *tokenIdStr = cartOptionalString(cart, hgh2UserTokenId);
if (!login || !pass || !tokenIdStr)
errAbort("User or password is missing");
int tokenId = atoi(tokenIdStr);
struct json *js = hgUsersLogin(cart, login, pass, tokenId);
hPrintf("%s", js->print(js));
}
void modeGetToken()
{
struct json *js = hgUsersGetToken(cart);
hPrintf("%s", js->print(js));
}
void modeGetDatasets()
{
if (!ghList)
return;
struct genoHeatmap *gh;
struct slRef *ref;
struct dataset *da;
struct datasetGroup *gr, *groups = NULL;
for (ref = ghList; ref; ref = ref->next)
{
gh = ref->val;
char *group = gh->group;
if (!group)
group = "Misc."; // default name.
gr = datasetGroupFind(groups, group); // For some reason, slNameFind(...) doesn't work.
if (!gr)
{
AllocVar(gr);
gr->name = cloneString(group);
gr->datasets = NULL;
slAddHead(&groups, gr);
}
AllocVar(da);
da->name = cloneString(gh->name);
da->shortLabel = cloneString(gh->shortLabel);
da->longLabel = cloneString(gh->longLabel);
da->url = cloneString(gh->url);
da->expCount = gh->expCount;
slAddHead(&gr->datasets, da);
}
slReverse(&groups);
struct json *js = newJson();
for (gr = groups; gr; gr = gr->next)
{
slSort(&gr->datasets, datasetCmpShortLabel);
struct json *set, *group = jsonAddContainerList(js, gr->name);
set = group;
for (da = gr->datasets; da; da = da->next)
{
jsonAddString(set, "name", da->name);
jsonAddString(set, "shortLabel", da->shortLabel);
jsonAddString(set, "longLabel", da->longLabel);
jsonAddString(set, "url", da->url);
jsonAddInt(set, "N", da->expCount);
if (da->next)
set = jsonAddContainerToList(&group);
}
}
hPrintf("%s", js->print(js));
}
int getSampleHeight(struct genoHeatmap *gh)
{
int sampleHeight = cartUsualInt(cart, hgh2SampleHeight, hgSampleHeightDefault);
if (sampleHeight != hgSampleHeightDefault)
return sampleHeight;
int defaultHeight = heatmapHeight(gh);
sampleHeight = round((double) MIN_HEATMAP_HEIGHT / (double) defaultHeight);
if (sampleHeight < 1)
sampleHeight = 1;
return sampleHeight;
}
void modeGetSummary()
{
char *type = cartUsualString(cart, hgh2Type, "undefined");
char *dataset = cartOptionalString(cart, hgh2Dataset);
char *feature = cartUsualString(cart, hgh2Feature, "false");
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
// don't bother with sorting for summary view, just use default order.
// For some reason, sortPersonOrder(gh) screws this up. So don't use.
if (sameWord(gh->dataType, "bed 15"))
{
defaultOrder(gh);
setSubgroups(gh);
}
int sampleHeight = getSampleHeight(gh);
struct json *js = newJson();
if (sameString(type, "chrom"))
{
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
drawGenomeSummary(js, gh, chromStart, chromEnd, width, sampleHeight);
}
else if (sameString(type, "geneset"))
{
char *geneSets = cartOptionalString(cart, hgh2GeneSets);
char *userGeneset = cartOptionalString(cart, hgh2UserGeneSet);
drawGenesetSummary(js, gh, geneSets, userGeneset, width, sampleHeight);
}
else
errAbort("Unhandled type %s, mode = getHeatmaps", type);
setupFeatureVisibility(gh);
//setupSort(gh); // set any cart variables needed to perform sort.
if (sameWord(gh->dataType, "bed 15"))
setSubgroups(gh);
if (sameString(feature, "true"))
{
int featureWidth = cartUsualInt(cart, hgh2FeatureWidth, hgFeatureDefaultPixWidth);
drawFeatureSummaryHeatmap(js, gh, featureWidth, sampleHeight);
}
jsonSampleList(js, gh);
hPrintf("%s", js->print(js));
}
void modeGetHeatmaps()
{
char *type = cartUsualString(cart, hgh2Type, "undefined");
char *dataset = cartOptionalString(cart, hgh2Dataset);
char *feature = cartUsualString(cart, hgh2Feature, "false");
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
int sampleHeight = getSampleHeight(gh);
/**** END common stuff */
struct json *js = newJson();
if (sameString(type, "chrom"))
{
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
drawGenomeHeatmap(js, gh, chromStart, chromEnd, width, sampleHeight);
}
else if (sameString(type, "geneset"))
{
char *geneSets = cartOptionalString(cart, hgh2GeneSets);
char *userGeneset = cartOptionalString(cart, hgh2UserGeneSet);
drawGenesetHeatmap(js, gh, geneSets, userGeneset, width, sampleHeight);
}
else
errAbort("Unhandled type %s, mode = getHeatmaps", type);
if (sameString(feature, "true"))
{
int featureWidth = cartUsualInt(cart, hgh2FeatureWidth, hgFeatureDefaultPixWidth);
drawFeatureHeatmap(js, gh, featureWidth, sampleHeight);
}
jsonSampleList(js, gh);
hPrintf("%s", js->print(js));
}
void modeGetLabels()
{
char *type = cartUsualString(cart, hgh2Type, "undefined");
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
struct json *js = newJson();
if (sameString(type, "chrom"))
{
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
drawGenomeLabels(js, chromStart, chromEnd, width);
}
else if (sameString(type, "geneset"))
{
char *geneSets = cartOptionalString(cart, hgh2GeneSets);
char *userGeneset = cartOptionalString(cart, hgh2UserGeneSet);
drawGenesetsLabels(js, geneSets, userGeneset, width);
}
else
errAbort("Unhandled type %s, mode = getLabels", type);
hPrintf("%s", js->print(js));
}
void modeGetAnnotation()
{
char *table = "refGene";
char *type = cartUsualString(cart, hgh2Type, "undefined");
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
struct json *js = newJson();
if (sameString(type, "chrom"))
{
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
drawAnnotation(js, table, chromStart, chromEnd, width);
}
else
errAbort("Unhandled type %s, mode = getAnnotation", type);
hPrintf("%s", js->print(js));
}
void modeGetFeatures()
/* get a list of available features for dataset */
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
/**** END common */
struct json *js = newJson();
jsonFeatureList(js, gh);
hPrintf("%s", js->print(js));
}
void modeUpdateFeatures()
/* updates features, assumes heatmap has not changed */
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
int featureWidth = cartUsualInt(cart, hgh2FeatureWidth, hgFeatureDefaultPixWidth);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
/**** END common stuff */
int sampleHeight = getSampleHeight(gh);
struct json *js = newJson();
drawFeatureHeatmap(js, gh, featureWidth, sampleHeight);
hPrintf("%s", js->print(js));
}
void modeUpdateFeatureSummary()
/* updates features, assumes heatmap has not changed */
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
int featureWidth = cartUsualInt(cart, hgh2FeatureWidth, hgFeatureDefaultPixWidth);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
setSubgroups(gh);
/**** END common stuff */
int sampleHeight = getSampleHeight(gh);
struct json *js = newJson();
drawFeatureSummaryHeatmap(js, gh, featureWidth, sampleHeight);
hPrintf("%s", js->print(js));
}
void modeCheckGeneList()
/* Search genesets with a query for geneset name or containing gene */
{
char *searchGenes = cartOptionalString(cart, hgh2MatchingGenes);
searchGenes = cleanUpMemberStr(replaceChars(replaceChars(searchGenes, "\n", ",")," ",","));
struct slName *valList = getGenesMatchingList(searchGenes);
struct slName *errList = getGenesNotMatching(searchGenes);
struct json *js = newJson();
jsonAddSlName(js, "validated", valList);
jsonAddSlName(js, "error", errList);
/* output JSON string */
hPrintf("%s", js->print(js));
}
void modeGetGenes()
/* Search genesets with a query for geneset name or containing gene */
{
char *searchGenes = cartOptionalString(cart, hgh2MatchingGenes);
struct slName *slList = getGenesMatching(searchGenes);
struct json *js = newJson();
if (slCount(slList) > MAX_NUM_RESPONSE)
{
struct slName *sl = slElementFromIx(slList, MAX_NUM_RESPONSE);
if (sl)
sl->next = NULL;
}
jsonAddSlName(js, "genes", slList);
/* output JSON string */
hPrintf("%s", js->print(js));
}
void modeGetGenesets()
/* Search genesets with a query for geneset name or containing gene */
{
char *searchGenes = cartOptionalString(cart, hgh2MatchingGenes);
char *searchGenesets = cartOptionalString(cart, hgh2MatchingGenesets);
/* Searches both user genesets and genesets in db */
struct slName *slList = getGenesetsMatching(cart, searchGenes, searchGenesets);
struct json *js = newJson();
if (slCount(slList) > MAX_NUM_RESPONSE)
{
struct slName *sl = slElementFromIx(slList, MAX_NUM_RESPONSE);
if (sl)
sl->next = NULL;
}
jsonAddSlName(js, "geneSets", slList);
/* output JSON string */
hPrintf("%s", js->print(js));
}
void modeGetGenesInGenesets()
/* Search genesets with a query for geneset name or containing gene */
{
char *genesets = cartOptionalString(cart, hgh2GeneSets);
if (!genesets)
return;
struct slName *sl, *slList = slNameListFromComma(genesets);
struct json *js = newJson();
for (sl = slList; sl; sl = sl->next)
{
struct slName *genes = getGenesInGeneset(cart, sl->name);
char *desc = getDescriptionOfGeneset(sl->name);
if (desc)
jsonAddSlName(js, desc, genes);
else
jsonAddSlName(js, sl->name, genes);
}
/* output JSON string */
hPrintf("%s", js->print(js));
}
void modeStoreUserGeneset()
{
char *name = cartOptionalString(cart, hgh2UserGenesetName);
char *members = cartOptionalString(cart, hgh2UserGenesetMembers);
if (!name || !members)
return;
char *genesetName = storeUserGeneset(cart, name, members);
struct json *js = newJson();
jsonAddString(js, "genesetSaved", genesetName);
hPrintf("%s", js->print(js));
}
void modeSubgroup()
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
if (!dataset)
return;
/**** START stuff common to all datasets */
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
/**** END common stuff */
setSubgroups(gh);
int sampleHeight = getSampleHeight(gh);
int subgroupWidth = hghSubgroupDefaultPixWidth;
char *sGif = subgroupGif(gh, gh->name, subgroupWidth, sampleHeight);
struct json *js = newJson();
jsonAddString(js, "subgroupImg", sGif);
hPrintf("%s", js->print(js));
}
void modeStats()
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
if (!dataset)
return;
/**** START stuff common to all datasets */
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
jsonWarnAbort("%s is not accessible", dataset);
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
/**** END common stuff */
setSubgroups(gh);
char *statsFxn = cartOptionalString(cart, hgh2StatsFxn);
char *type = cartOptionalString(cart, hgh2Type);
if (!statsFxn || !type)
return;
int sampleHeight = getSampleHeight(gh);
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
int subsetNum = cartUsualInt(cart, hgh2SubgroupNum, hgh2SubgroupDefaultNum);
char *statsGif = NULL; /* JSON formatted response string */
char *scaleGif = NULL;
if (sameString(type, "chrom"))
{
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
drawGenomeStats(gh, statsFxn, chromStart, chromEnd,
subsetNum, width, sampleHeight, &statsGif, &scaleGif);
}
else if (sameString(type, "geneset"))
{
char *geneSets = cartOptionalString(cart, hgh2GeneSets);
char *userGeneset = cartOptionalString(cart, hgh2UserGeneSet);
drawGenesetStats(gh, statsFxn, geneSets, userGeneset,
subsetNum, width, sampleHeight, &statsGif, &scaleGif);
}
else
errAbort("Unhandled type %s, mode = getHeatmaps", type);
struct json *js = newJson();
jsonAddString(js, "statsImg", statsGif);
jsonAddString(js, "scale", scaleGif);
hPrintf("%s", js->print(js));
}
void modeGetScale()
{
int width = cartUsualInt(cart, hgh2Width, hgHeatmapDefaultPixWidth);
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
char *startChrom = NULL;
int startBase = -1;
char *endChrom = NULL;
int endBase = -1;
parseChromStrings(chromStart, &startChrom, &startBase,
chromEnd, &endChrom, &endBase);
struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, database);
struct genoLayChrom *chrom, *allChromList = genoLayDbChroms(conn, FALSE);
if (!allChromList)
return;
if (!startChrom)
startChrom = cloneString(allChromList->fullName);
if (!endChrom)
for (chrom = allChromList; chrom; chrom = chrom->next)
if (!chrom->next)
endChrom = cloneString(chrom->fullName);
int keepChroms = 0;
double totalBases = 0.0;
for (chrom = allChromList; chrom != NULL; chrom = chrom->next)
{
if (sameString(chrom->fullName, startChrom))
keepChroms = 1;
if (keepChroms)
{
int baseStart = -1;
int baseEnd = -1;
if (sameString(chrom->fullName, startChrom) && (startBase != -1))
baseStart = startBase;
if (sameString(chrom->fullName, endChrom) && (endBase != -1))
{
if (endBase > chrom->size)
endBase = chrom->size;
baseEnd = endBase + 1;
}
if (baseStart < 0)
baseStart = 0;
if (baseEnd < 0)
baseEnd = chrom->size;
totalBases += baseEnd - baseStart;
}
if (sameString(chrom->fullName, endChrom))
keepChroms = 0;
}
struct heatmapLay *hl = chromLayout(conn, NULL, startChrom, startBase,
endChrom, endBase, width, 1);
hFreeConn(&conn);
char *scaleGif = genomeScaleGif(hl, totalBases);
struct json *js = newJson();
jsonAddString(js, "scaleImg", scaleGif);
hPrintf("%s", js->print(js));
}
void toolTipQuery()
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
char *sampleId = cartOptionalString(cart, hgh2Sample);
char *probeId = cartOptionalString(cart, hgh2Probe);
char *feature = cartOptionalString(cart, hgh2Feature);
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
/**** START stuff common to all datasets */
if (!ghHash || !dataset)
return;
struct hashEl *el = hashLookup(ghHash, dataset);
if (!el)
return;
struct genoHeatmap *gh = el->val;
setupFeatureVisibility(gh);
setupSort(gh); // set any cart variables needed to perform sort.
/**** END common stuff */
if (!sampleId)
jsonWarnAbort("Tooltip query requires sample id.");
char *val = NULL;
if (probeId)
val = toolTipByProbe(gh, sampleId, probeId);
else if (feature)
val = toolTipByFeature(gh, sampleId, feature);
else if (chromStart && chromEnd)
{
char *startChrom = NULL;
int start = -1;
char *stopChrom = NULL;
int stop = -1;
parseChromStrings(chromStart, &startChrom, &start,
chromEnd, &stopChrom, &stop);
if (!sameString(startChrom, stopChrom))
jsonWarnAbort("Tooltip query across two (or more) chromosomes not allowed.");
if (start == -1 || stop == -1)
jsonWarnAbort("Tooltip query start/stop value not defined.");
val = toolTipByChromPos(gh, sampleId, startChrom, start, stop);
}
else
jsonWarnAbort("Tooltip query ill-defined.");
struct json *js = newJson();
if (val)
jsonAddString(js, "value", val);
else
jsonAddString(js, "value", "N/A");
hPrintf("%s", js->print(js));
}
void toolTipGeneQuery()
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
char *chromStart = cartOptionalString(cart, hgh2ChromStart);
char *chromEnd = cartOptionalString(cart, hgh2ChromEnd);
/**** START stuff common to all datasets */
if (!dataset || !chromStart || !chromEnd)
jsonWarnAbort("Tooltip (refGene) query ill-defined.");
int maxNumGenes = 10; // Maximum # of genes to return in response
char *startChrom = NULL;
int start = -1;
char *stopChrom = NULL;
int stop = -1;
parseChromStrings(chromStart, &startChrom, &start,
chromEnd, &stopChrom, &stop);
if (!sameString(startChrom, stopChrom))
jsonWarnAbort("Tooltip query across two (or more) chromosomes not allowed.");
if (start == -1 || stop == -1)
jsonWarnAbort("Tooltip query start/stop value not defined.");
char *val = toolTipGeneTrackByChromPos(database, dataset, startChrom,
start, stop, maxNumGenes);
struct json *js = newJson();
if (val)
jsonAddString(js, "value", val);
else
jsonAddString(js, "value", "N/A");
hPrintf("%s", js->print(js));
}
void modeToolTipQuery()
{
char *dataset = cartOptionalString(cart, hgh2Dataset);
if (!dataset)
return;
if (sameString(dataset, "refGene"))
toolTipGeneQuery();
else
toolTipQuery();
}
/* ----------------------------------------------------------- */
void dispatchRoutines()
/* Look at command variables in cart and figure out which
* page to draw. */
{
/* retrieve cart variables, handle various modes */
char *mode = cartOptionalString(cart, hgh2Mode);
if (!mode)
errAbort("%s is required.", hgh2Mode);
if (sameString(mode, "getDatasets"))
modeGetDatasets();
else if (sameString(mode, "getHeatmaps"))
modeGetHeatmaps();
else if (sameString(mode, "getCircleMap"))
modeGetCircleMap();
else if (sameString(mode, "getLabels"))
modeGetLabels();
else if (sameString(mode, "getAnnotation"))
modeGetAnnotation();
else if (sameString(mode, "getSummary"))
modeGetSummary();
else if (sameString(mode, "getFeatures"))
modeGetFeatures();
else if (sameString(mode, "updateFeatures"))
modeUpdateFeatures();
else if (sameString(mode, "updateFeatureSummary"))
modeUpdateFeatureSummary();
else if (sameString(mode, "getGenesets"))
modeGetGenesets();
else if (sameString(mode, "getGenes"))
modeGetGenes();
else if (sameString(mode, "checkGeneList"))
modeCheckGeneList();
else if (sameString(mode, "subgroup"))
modeSubgroup();
else if (sameString(mode, "stats"))
modeStats();
else if (sameString(mode, "tooltipQuery"))
modeToolTipQuery();
else if (sameString(mode, "getGenesInGenesets"))
modeGetGenesInGenesets();
else if (sameString(mode, "storeUserGeneset"))
modeStoreUserGeneset();
else if (sameString(mode, "getScale"))
modeGetScale();
else if (sameString(mode, "save"))
modeSave();
else if (sameString(mode, "load"))
modeLoad();
else if (sameString(mode, "getToken"))
modeGetToken();
else if (sameString(mode, "login"))
modeLogin();
else if (sameString(mode, "getUserDatasets"))
modeGetUserDatasets();
else
errAbort("Incorrect mode = %s", mode);
cartRemovePrefix(cart, advFilterPrefix);
cartRemovePrefix(cart, colConfigPrefix);
cartRemovePrefix(cart, colOrderVar);
cartRemovePrefix(cart, hghPrefix);
cartRemovePrefix(cart, hgh2Prefix);
}
void hghDoUsualHttp()
/* Wrap html page dispatcher with code that writes out
* HTTP header and write cart back to database. */
{
cartWriteCookie(cart, hUserCookie());
printf("Content-Type:application/x-javascript\r\n\r\n");
/* Dispatch other pages, that actually want to write HTML. */
cartWarnCatcher(dispatchRoutines, cart, jsonEarlyWarningHandler);
cartCheckout(&cart);
}
void dispatchLocation()
/* When this is called no output has been written at all. We
* look at command variables in cart and figure out if we just
* are going write an HTTP location line, which happens when we
* want to invoke say the genome browser or gene sorter without
* another intermediate page. If we need to do more than that
* then we call hghDoUsualHttp. */
{
/* set up the global database variable, currently force to be hg18, instead of
* using getDbAndGeneome(cart, &database, &genome, oldVars). This avoids a bug
* when the cart is set to a different db, which occurs when a user was browsing
* a different genome in the general genome browser */
database = cloneString("hg18");
cartSetString(cart, "db", database); /* custom tracks needs this */
/* set up heatmap data for all display modes*/
theDataset = cartUsualString(cart, hghDataSet, "ALL");
getGenoHeatmaps(theDataset);
/* For other cases we want to print out some of the usual HTTP
* lines including content-type */
hghDoUsualHttp();
}
char *excludeVars[] = {"Submit", "submit", NULL};
int main(int argc, char *argv[])
/* Process command line. */
{
htmlPushEarlyHandlers();
cgiSpoof(&argc, argv);
htmlSetStyle(htmlStyleUndecoratedLink);
if (argc != 1)
usage();
oldVars = hashNew(12);
cart = cartForSession(hUserCookie(), excludeVars, oldVars);
dispatchLocation();
return 0;
}