src/hg/instinct/hgBamBam/hgBamBam.c 1.8

1.8 2010/06/01 06:29:06 jsanborn
updated
Index: src/hg/instinct/hgBamBam/hgBamBam.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgBamBam/hgBamBam.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -b -B -U 1000000 -r1.7 -r1.8
--- src/hg/instinct/hgBamBam/hgBamBam.c	1 Jun 2010 04:00:48 -0000	1.7
+++ src/hg/instinct/hgBamBam/hgBamBam.c	1 Jun 2010 06:29:06 -0000	1.8
@@ -1,476 +1,477 @@
 /* hgBamBam */
 #include "common.h"
 #include "bed.h"
 #include "cart.h"
 #include "linefile.h"
 #include "genoLay.h"
 #include "hash.h"
 #include "hCommon.h"
 #include "hdb.h"
 #include "hPrint.h"
 #include "htmshell.h"
 #include "hui.h"
 #include "trackLayout.h"
 #include "web.h"
 #include "json.h"
 #include "hgBamBam.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 *db = "pdata";
 char *localDb = "localDb";
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "hgBamBam\n"
   "usage:\n"
   "   hgBamBam\n"
   );
 }
 
 /****** BEGIN HELPER FUNCTIONS *******/
 
 
 struct bed *getBed(struct sqlConnection *conn, char *tableName, char *pos, int nField) 
 {
 /* get the data from the database */
 char **row = NULL;
 char query[512];
 query[0] = '\0';
     
 if (!pos)
     safef(query, sizeof(query), "select * from %s", tableName);
 else
     {
     char *chrom = NULL;
     int start = 0;
     int stop = 0;
     if (!hgParseChromRange(NULL, pos, &chrom, &start, &stop))
 	return NULL;
     
     safef(query, sizeof(query),
 	  "select * from %s where chrom = '%s' and chromStart<%d and chromEnd>%d",
 	  tableName, chrom, stop, start);
     }
 
 struct sqlResult *sr = sqlGetResult(conn, query);
 struct bed *tuple = NULL;
 struct bed *tupleList = NULL;
 
 /* all copy number tracks are bed 4 */
 while ((row = sqlNextRow(sr)) != NULL)
     {
     tuple = bedLoadN(row+1, nField);
     slAddHead(&tupleList, tuple);
     }
 
 slReverse(&tupleList);
 sqlFreeResult(&sr);
 return tupleList;
 }
 
 
 struct breaks *getBreaks(struct sqlConnection *conn, char *tableName, char *pos, boolean intra)
 {
 /* get the data from the database */
 char **row = NULL;
 char query[512];
 query[0] = '\0';
     
 if (!pos)
     {
     if (intra)
 	safef(query, sizeof(query), "select * from %s where chrom = chrom2", tableName);
     else
 	safef(query, sizeof(query), "select * from %s where chrom != chrom2", tableName);
     }
 else
     {
     char *chrom = NULL;
     int start = 0;
     int stop = 0;
     if (!hgParseChromRange(NULL, pos, &chrom, &start, &stop))
 	return NULL;
 
     if (intra)
 	safef(query, sizeof(query),
 	      "select * from %s where chrom = chrom2 and chrom = '%s' and (chromStart<%d and chromEnd>%d) or (chromStart2<%d and chromEnd2>%d) or (chromStart<%d and chromEnd2>%d) or (chromStart2<%d and chromEnd>%d)",
 	      tableName, chrom, stop, start, stop, start, stop, start, stop, start);
     else
 	safef(query, sizeof(query),
 	      "select * from %s where chrom != chrom2 and ((chrom = '%s' and chromStart<%d and chromEnd>%d) or (chrom2 = '%s' and chromStart2<%d and chromEnd2>%d))",
 	      tableName, chrom, stop, start, chrom, stop, start);
     }
 
 struct sqlResult *sr = sqlGetResult(conn, query);
 struct breaks *br, *brList = NULL;
 
 /* all copy number tracks are bed 4 */
 while ((row = sqlNextRow(sr)) != NULL)
     {
     AllocVar(br);
 
     br->chrom = cloneString(row[0]);
     br->chromStart = atoi(row[1]);
     br->chromEnd = atoi(row[2]);
     strcpy(br->strand, row[3]);
     br->chrom2 = cloneString(row[4]);
     br->chromStart2 = atoi(row[5]);
     br->chromEnd2 = atoi(row[6]);
     strcpy(br->strand2, row[7]);
     br->support = atoi(row[8]);
     br->qual = atof(row[9]);
 
     slAddHead(&brList, br);
     }
 slReverse(&brList);
 sqlFreeResult(&sr);
 return brList;
 }
 
 
 /****** END HELPER FUNCTIONS *******/
 
 
 float drawCopy(struct sqlConnection *conn, struct json *js, 
 	       char *pos, int width, int height, char *sampleName, char *suffix,
 	       char *title, float maxVal, float medVal, Color col)
 {
 char tableName[256];
 safef(tableName, sizeof(tableName), "%s_%s", sampleName, suffix);
 
 struct bed *bed = getBed(conn, tableName, pos, 4); 
 
 struct settings *settings = initSettings(conn, pos, title, width, height, 0.0, maxVal);
 
 char *filename = copyNumberGif(conn, bed, settings, suffix, 0.0, col);
 if (!filename)
     return 0.0;
 
 char jsName[256];
 safef(jsName, sizeof(jsName), "image_%s", suffix);
 jsonAddString(js, jsName, filename);
 
 bedFree(&bed);
 
 return settings->maxVal;
 }
 
 void drawInterBreaks(struct sqlConnection *conn, struct json *js, 
 		     char *pos, int width, char *name, char *suffix)
 {
 char tableName[256];
 safef(tableName, sizeof(tableName), "%s_%s", name, suffix);
 
 int height = DEFAULT_LABEL_HEIGHT;
 struct breaks *breaks = getBreaks(conn, tableName, pos, FALSE);  // FALSE = inter
 
 struct settings *settings = initSettings(conn, pos, "Inter-Chromosomal Breaks", width, height, 0, 0);
 
 char *filename = interBreaksGif(conn, breaks, settings);
 if (!filename)
     return;
 
 char jsName[256];
 safef(jsName, sizeof(jsName), "inter_%s", suffix);
 jsonAddString(js, jsName, filename);
 jsonAddInt(js, "interBreaksHeight", settings->height);
 }
 
 void drawIntraBreaks(struct sqlConnection *conn, struct json *js, 
 	       char *pos, int width, char *name, char *suffix)
 {
 char tableName[256];
 safef(tableName, sizeof(tableName), "%s_%s", name, suffix);
 
 int height = DEFAULT_LABEL_HEIGHT;
 struct breaks *breaks = getBreaks(conn, tableName, pos, TRUE);  // TRUE = intra
 
 struct settings *settings = initSettings(conn, pos, "Intra-Chromosomal Breaks", width, height, 0, 0);
 
 char *filename = intraBreaksGif(conn, breaks, settings);
 if (!filename)
     return;
 
 char jsName[256];
 safef(jsName, sizeof(jsName), "intra_%s", suffix);
 jsonAddString(js, jsName, filename);
 jsonAddInt(js, "intraBreaksHeight", settings->height);
 }
 
 void drawIdeo(struct sqlConnection *conn, struct json *js, 
 	      char *pos, int width)
 {
 int height = DEFAULT_LABEL_HEIGHT + CYTO_HEIGHT;
 struct settings *settings = initSettings(conn, pos, NULL, width, height, 0, 0);
 
 char *filename = genomeLabelsGif(conn, settings);
 if (!filename)
     return;
 
 jsonAddString(js, "ideogram", filename);
 }
 
 
 void drawGenes(struct sqlConnection *conn, struct json *js, 
 	      char *pos, int width)
 {
 int height = DEFAULT_LABEL_HEIGHT + TITLE_HEIGHT;
 struct settings *settings = initSettings(conn, pos, "RefSeq Genes", width, height, 0, 0);
 
 char *filename = annotationGif(settings, "refGene");
 if (!filename)
     return;
 
 jsonAddString(js, "genes", filename);
 jsonAddInt(js, "genesHeight", settings->height);
 }
 
 void drawSNPs(struct sqlConnection *conn, struct json *js, 
 	      char *pos, int width, char *name, char *suffix)
 {
 int height = DEFAULT_LABEL_HEIGHT;
 struct settings *settings = initSettings(conn, pos, 
 					 "Single Nucleotide Variants", width, height, 0, 0);
 
 char tableName[256];
 safef(tableName, sizeof(tableName), "%s_%s", name, suffix);
 
 char *filename = snpsGif(settings, tableName);
 if (!filename)
     return;
 
 char jsName[256];
 safef(jsName, sizeof(jsName), "image_%s", suffix);
 jsonAddString(js, jsName, filename);
 
 jsonAddInt(js, "snpsHeight", settings->height);
 }
 
 
 void drawScale(struct sqlConnection *conn, struct json *js, 
 	      char *pos, int width)
 {
 int height = DEFAULT_LABEL_HEIGHT;
 struct settings *settings = initSettings(conn, pos, NULL, width, height, 0, 0);
 
 char *filename = genomeScaleGif(settings);
 if (!filename)
     return;
 
 jsonAddString(js, "scale", filename);
 }
 
 char *getPosition(struct genoLayChrom *glList)
 {
 char *pos = cartUsualString(cart, bbPos, NULL);
 
 if (!pos)
     return NULL;
 
 if (sameString(pos, ""))
     return NULL;
 
 char *chrom;
 int start = -1, stop = -1;
 
 struct genoLayChrom *gl;
 for (gl = glList; gl; gl = gl->next)
     {
     if (!sameString(gl->fullName, pos))
 	continue;
     break;
     }
 
 if (gl) // only single chrom (e.g. "chr7") given as input.
     chrom = cloneString(gl->fullName);
 else
     {
     if (!hgParseChromRange(NULL, pos, &chrom, &start, &stop))
 	return NULL;
 
     for (gl = glList; gl; gl = gl->next)
 	{
 	if (!sameString(gl->fullName, chrom))
 	    continue;
 	break;
 	}
     if (!gl)
 	return NULL;
     }
 
 if (start <= 0 && stop <= 0)
     {
     start = 1;
     stop  = gl->size - 1;
     }
 
 if (start <= 0)
     start = 1;
 else if (start > gl->size - 1)
     start = gl->size - 1;
 
 if (stop <= 0)
     stop = 1;
 else if (stop > gl->size - 1)
     stop = gl->size - 1;
 
 char newPos[256];
 safef(newPos, sizeof(newPos), "%s:%d-%d", chrom, start, stop);
 
 return cloneString(newPos);
 }
 
 void draw()
 {
 struct sqlConnection *conn = hAllocConnProfile(localDb, db);
 
 struct genoLayChrom *glList = genoLayDbChroms(conn, FALSE);
 
 char *pos = getPosition(glList);
 
 int width  = cartUsualInt(cart, bbWidth, DEFAULT_PLOT_WIDTH);
 int height = cartUsualInt(cart, bbHeight, DEFAULT_PLOT_HEIGHT);
 
 char *name = cartUsualString(cart, bbSampleName, NULL);
 if (!name)
     return;
 
 struct json *js = newJson();
 float maxVal = FLOAT_NULL;
 drawCopy(conn, js, pos, width, height, name, 
 	 "cnv", "Overall Copy Number", FLOAT_NULL, 0.0, MG_BLACK);
 
 /* set max val according to majority copy number */
 maxVal = drawCopy(conn, js, pos, width, height, name, 
 		  "major", "Majority Copy Number", maxVal, 0.0, MG_RED);
 drawCopy(conn, js, pos, width, height, name, 
 	 "minor", "Minority Copy Number", maxVal, 0.0, MG_BLUE);
 
 drawSNPs(conn, js, pos, width, name, "snps");
 drawInterBreaks(conn, js, pos, width, name, "breaks");
 drawIntraBreaks(conn, js, pos, width, name, "breaks");
 
 drawIdeo(conn, js, pos, width);
 drawGenes(conn, js, pos, width);
 drawScale(conn, js, pos, width);
 
 if (pos)
     jsonAddString(js, "pos", pos);
 else
     jsonAddString(js, "pos", "");
 
 struct settings *settings = initSettings(conn, pos, "settings", width, height, 0, 0);
 
 if (settings)
     {
     struct json *new, *list = jsonAddContainerList(js, "chroms");
     new = list;
     
     struct chromLay *cl;
     for (cl = settings->layoutList; cl; cl = cl->next)
 	{
 	jsonAddString(new, "name", cl->chrom);
 	jsonAddDouble(new, "baseStart", cl->baseStart);
 	jsonAddDouble(new, "baseEnd", cl->baseEnd);
 	jsonAddDouble(new, "baseWidth", cl->baseWidth);
 	jsonAddInt(new, "pxStart", cl->pxStart);
 	jsonAddInt(new, "pxStop", cl->pxStart + cl->pxWidth);
 	jsonAddInt(new, "pxWidth", cl->pxWidth);
 	
 	if (cl->next)
 	    new = jsonAddContainerToList(&list);
 	}
     }
 if (js)
     hPrintf("%s\n", js->print(js));
 
 hFreeConn(&conn);
 }
 
 void share()
 {
 char *emailTo   = cartUsualString(cart, bbEmailTo, NULL);
 char *emailFrom = cartUsualString(cart, bbEmailFrom, NULL);
+char *emailSubject = cartUsualString(cart, bbEmailSubject, "UCSC BamBam Browser link");
 char *link      = cartUsualString(cart, bbLink, NULL);
 
 struct json *js = newJson();
 
 if (!emailTo || !emailFrom || !link)
-    jsonAddString(js, "response", "All fields must be filled.");
+    jsonAddString(js, "response", "Email fields must be filled.");
 else
     {
     char cmd[1024];
     safef(cmd, sizeof(cmd),
 	  "echo 'User %s wanted you to check out:\n\n%s\n\nCourtesy of the UCSC BamBam Browser.'"
-	  "| mail -s \"UCSC BamBam Browser link\" -c %s %s",
-	  emailFrom, link, emailFrom, emailTo);
+	  "| mail -s \"%s\" -c %s %s",
+	  emailFrom, link, emailSubject, emailFrom, emailTo);
 
     int result = system(cmd);
     if (result == -1)
 	jsonAddString(js, "response", "Error sending email.");
     else
 	{ 
 	char response[256];
-	safef(response, sizeof(response), "Email sent to %s", emailTo);
+	safef(response, sizeof(response), "Email sent");
 	jsonAddString(js, "response", response);
 	}
     }
 
 if (js)
     hPrintf("%s\n", js->print(js));
 }
 
 
 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, bbMode);
 if (!mode)
     errAbort("%s is required.", bbMode);
 
 if (sameString(mode, "draw"))
     draw();
 else if (sameString(mode, "share"))
     share();
 else
     errAbort("Incorrect mode = %s", mode);
 
 cartRemovePrefix(cart, bbPrefix);
 }
 
 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);
 }
 
 char *excludeVars[] = {"Submit", "submit", NULL};
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 htmlPushEarlyHandlers();
 cgiSpoof(&argc, argv);
 htmlSetStyle(htmlStyleUndecoratedLink);
 
 oldVars = hashNew(12);
 cart = cartForSession(hUserCookie(), excludeVars, oldVars);
 
 hghDoUsualHttp();
 return 0;
 }