e70152e44cc66cc599ff6b699eb8adc07f3e656a
kent
  Sat May 24 21:09:34 2014 -0700
Adding Copyright NNNN Regents of the University of California to all files I believe with reasonable certainty were developed under UCSC employ or as part of Genome Browser copyright assignment.
diff --git src/hg/hgc/rnaFoldClick.c src/hg/hgc/rnaFoldClick.c
index b76a120..6da4a60 100644
--- src/hg/hgc/rnaFoldClick.c
+++ src/hg/hgc/rnaFoldClick.c
@@ -1,505 +1,508 @@
 /* Handle details pages for rna fold (evofold) tracks. */
 
+/* Copyright (C) 2013 The Regents of the University of California 
+ * See README in this or parent directory for licensing information. */
+
 #include "common.h"
 #include "jksql.h"
 #include "hgMaf.h"
 #include "maf.h"
 #include "cart.h"
 #include "hgc.h"
 #include "hCommon.h"
 #include "hgColors.h"
 #include "obscure.h"
 #include "customTrack.h"
 #include "htmshell.h"
 #include "rnautil.h"
 #include "rnaSecStr.h"
 #include "memalloc.h"
 
 
 /* Taken from hgc.c (should probably be in hgc.h)*/
 #define RED 0xFF0000
 #define GREEN 0x00FF00
 #define BLUE 0x0000FF
 #define BLACK 0x000000
 #define CYAN 0x00FFFF
 #define GRAY 0xcccccc
 #define LTGRAY 0x999999
 #define ORANGE 0xDD6600
 #define MAGENTA 0xFF00FF
 
 #define LTPURPLE 0x9966CC
 #define SCORE_SHADES_COUNT 10
 
 void printRfamUrl(char *itemName)
 /* Print a link to the Rfam entry corresponding to the item. */
 {
 char *query = cloneString(itemName);
 char *end   = strchr(query, '.');
 if (!end)
     return;
 else
     *end = 0;
 printf("<p><A HREF=\"");
 printf("http://www.sanger.ac.uk/cgi-bin/Rfam/seqget.pl?name=%s", query);
 printf("\" TARGET=_blank>%s</A></p>", itemName);
 freeMem(query);
 }
 
 void doubleArray2binArray(double *scores, int size, double minScore, double maxScore, int *binArray, int binCount)
 /* Will assign a bin to each score in 'scores' and store it in 'binArray' */
 {
 int i;
 for (i = 0; i < size; i++)
     binArray[i] = assignBin(scores[i], minScore, maxScore, binCount);
 }
 
 void htmlColorPrintString(FILE *f, char *s, int *colorFormat, int *colors, int L)
 /* Prints s to f wrapping characters in html tags for coloring
  * according to colorFormat and colors. colorFormat must be of same
  * length as s. Each position of colorFormat defines which of the
  * colors to use. Use 0 for default color. If L is non-NULL it
  * defines a mximum length to print.*/
 {
 int i;
 
 if (!L || (L && strlen(s)<L) )
     L = strlen(s);
 
 fprintf(f, "<span style='color:#%06X;'>", colors[0]); /* default color */
 for (i = 0; i < L; i++)
     {
     if (colorFormat[i] == 0)
 	fprintf(f, "%c", s[i]);
     else
 	fprintf(f, "<span style='color:#%06X;'>%c</span>", colors[ colorFormat[i] ], s[i]);
     }
 fprintf(f, "</span>");
 }
 
 void mafAndFoldHeader(FILE *f)
 /* Print header for maf and fold the section*/
 {
 fprintf(f, "<center><h2> Multiple alignment and RNA secondary structure annotation </h2></center>");
 }
 
 void mkPosString(char *s, int size)
 /* Make a string-ruler with a decimal every tenth position */
 {
 int i, d;
 for (i = 0, d = 0; i < size; i++)
     if (i%10 == 0)
 	{
 	s[i] = '0' + d;
 	d++;
 	if (d == 10)
 	  d = 0;
 	}
     else
 	s[i] = ' ';
 s[size] = '\0';
 }
 
 char *mkScoreString(double *scores, int L, char *referenceText)
     /* allocate string of score symbols, adjust for gaps in reference sequene */
 {
 char *s = (char *) needMem(L+1);
 char *scoreString = NULL;
 int i, n;
 for (i=0;i<L;i++)
     {
     n    = floor(10 *scores[i]);
     if (n == 10)
 	n = 9;
     if (n < 0 || n > 9)
 	errAbort( "Score not between 0 and 1\n" );
     s[i] = '0' + n;
     }
 s[L] = 0;
 scoreString = gapAdjustFold(s, referenceText);
 freeMem(s);
 return scoreString;
 }
 
 int *mkScoreColorFormat(double *scores, int L, char *referenceText)
   /* allocate string of score colors (gray shades), adjust for gaps in reference sequene */
 {
 int *v = NULL;
 int *scoreColorFormat = NULL;
 v = (int *) needMem(L *sizeof(int) );
 doubleArray2binArray(scores, L, 0.0, 1.0, v, SCORE_SHADES_COUNT);
 scoreColorFormat = gapIntArrayAdjust(v, referenceText);
 freeMem(v);
 return scoreColorFormat;
 }
 
 void defineMafSubstColors(int **p2mafColors)
 /* Defines the colors used for maf coloring. Must corrspsond to the
  * markCompensatoryMutations function.*/
 {
 int *mafColors;
 AllocArray(*p2mafColors, 8);
 mafColors = *p2mafColors;
 mafColors[0]    = LTGRAY;   /* not pairing */
 mafColors[1]    = LTPURPLE; /* not pairing, substitution */
 mafColors[2]    = BLACK;    /* compatible with pairing */
 mafColors[3]    = BLUE;     /* compatible with pairing, single substitution  */
 mafColors[4]    = GREEN;    /* compensatory change */
 mafColors[5]    = RED;      /* not compatible with fold, single subs */
 mafColors[6]    = ORANGE;   /* not compatible with fold, double subs */
 mafColors[7]    = MAGENTA;  /* not compatible with fold, involves indel */
 }
 
 char *hDbOrganism(char *databaseIn)
 /* Function to get organism from the genome db */
 {
 struct sqlConnection *connCentral = hConnectCentral();
 char buf[256];
 char query[256];
 char *res = NULL;
 char *database;
 char *chp;
 
 database = cloneString(databaseIn);
 
 // process special case like "hg19.chr21"
 chp = strstr(database, ".");
 if (chp != NULL)
     {
     *chp = '\0';
     }
 
 sqlSafef(query, sizeof(query), "select organism from dbDb where name = '%s'", database);
 if(sqlQuickQuery(connCentral, query, buf, sizeof(buf)) == NULL)
     // this can happen in mirrors (see #8490).
     errAbort("organism '%s' not found in dbDb", database);
 else
     res = cloneString(buf);
 hDisconnectCentral(&connCentral);
 freez(&database);
 return res;
 }
 
 
 void htmlPrintMafAndFold(FILE *f, struct mafAli *maf, char *fold, double *scores, int lineSize)
 /* HTML pretty print maf and fold to f. If scores is non-null then
  * scores are indicated below alignemnt.*/
 {
 struct mafComp *mc;
 int  i, N, lineStart, lineEnd;
 int  *pairList = NULL;
 int  *mafColors = NULL;
 int  **mafColorFormats = NULL;
 int  *scoreColorFormat = NULL;
 int  scoreColors[]  = {0x999999,0x888888,0x777777,0x666666,0x555555,0x444444,0x333333,0x222222,0x111111,0x000000};
 char *scoreString = 0;
 char *pairSymbols;
 char *posString, *adjPosString;
 char *adjFold;
 char foldTag[]       = "SS anno";
 char scoresTag[]     = "score  ";
 char positionTag[]   = "offset";
 char pairSymbolsTag[]= "pair symbol";
 char *referenceText  = maf->components->text; /* first sequence in the alignment */
 int  srcChars        = max( strlen(foldTag), strlen(pairSymbolsTag));
 int  refLength       = strlen(referenceText);
 int  foldLength      = strlen(fold);
 
 
 /* Adjust fold to gap structure in referenceText */
 adjFold = gapAdjustFold(fold, referenceText);
 
 /* make arrays for color formatting */
 N = slCount(maf->components);
 AllocArray(mafColorFormats, N);
 for (i = 0; i < N; i++)
     AllocArray(mafColorFormats[i], refLength);
 fold2pairingList(adjFold, refLength, &pairList);
 
 for (mc = maf->components, i = 0; mc != NULL; mc = mc->next, i++)
     markCompensatoryMutations(mc->text, referenceText, pairList, mafColorFormats[i]);
 defineMafSubstColors(&mafColors);
 
 /* Make pos string */
 posString = needMem(foldLength + 1);
 mkPosString(posString, foldLength);
 adjPosString = gapAdjustFold(posString, referenceText);
 
 /* Make a symbol string indicating pairing partner */
 pairSymbols = (char *) needMem(refLength + 1);
 mkPairPartnerSymbols(pairList, pairSymbols, refLength);
 
 /* Make the score string and its colorFormat */
 if (scores)
      {
      scoreString      = mkScoreString(scores, foldLength, referenceText);
      scoreColorFormat = mkScoreColorFormat(scores, foldLength, referenceText);
      }
 
 /* Find max. length of source (species) field. */
 for (mc = maf->components; mc != NULL; mc = mc->next)
     {
     int len = strlen(mc->src)+strlen(hDbOrganism(mc->src)) + 1;
     if (srcChars < len)
         srcChars = len;
     }
 
 /* Pretty print maf and fold */
 fprintf(f, "<PRE><TT>");
 for (lineStart = 0; lineStart < maf->textSize; lineStart = lineEnd)
     {
     int size;
     char buf[256];
     lineEnd = lineStart + lineSize;
     if (lineEnd >= maf->textSize)
         lineEnd = maf->textSize;
     size = lineEnd - lineStart;
     fprintf(f, "%-*s %.*s\n", srcChars, positionTag, lineSize, adjPosString + lineStart);
     for (mc = maf->components, i = 0; mc != NULL; mc = mc->next, i++)
         {
 	safef(buf, sizeof(buf), "%s/%s", mc->src, hDbOrganism(mc->src));
 	fprintf(f, "%-*s ", srcChars, buf);
 	htmlColorPrintString(f, mc->text + lineStart, mafColorFormats[i] + lineStart, mafColors, lineSize);
 	fprintf(f, "\n");
 	}
     fprintf(f, "%-*s %.*s\n", srcChars, foldTag, lineSize, adjFold + lineStart);
     fprintf(f, "%-*s %.*s\n", srcChars, pairSymbolsTag, lineSize, pairSymbols + lineStart);
     if (scores)
 	{
 	fprintf(f, "%-*s ", srcChars, scoresTag);
 	htmlColorPrintString(f, scoreString + lineStart, scoreColorFormat + lineStart, scoreColors, lineSize);
 	fprintf(f, "\n");
 	}
     fprintf(f, "\n");
     }
 fprintf(f, "</PRE></TT>");
 
 /* clean up*/
 freeMem(posString);
 freeMem(adjPosString);
 freeMem(adjFold);
 freeMem(pairSymbols);
 if (scores)
     {
     freeMem(scoreString);
     freeMem(scoreColorFormat);
     }
 for (i = 0; i < N; i++)
     freeMem(mafColorFormats[i]);
 freeMem(mafColorFormats);
 }
 
 void mafAndFoldLegend(FILE *f)
 /* Print legend for the maf and fold section */
 {
 char *s          = "0123456789";
 int colorFormat[] = {0,1,2,3,4,5,6,7,8,9};
 int colors[]      = {0x999999,0x888888,0x777777,0x666666,0x555555,0x444444,0x333333,0x222222,0x111111,0x000000};
 fprintf(f, "<h3> Color legend </h3>");
 fprintf(f, "<TABLE BORDER=0>");
 fprintf(f, "<TR> <TD style='color:#%06X;'> GRAY:       </TD> "
            "<TD> Not part of annotated pair, no substitution. <BR>             </TD> </TR>",
            LTGRAY);
 fprintf(f, "<TR> <TD style='color:#%06X;'> LT. PURPLE: </TD> "
            "<TD> Not part of annotated pair, substitution. <BR>                </TD> </TR>",
            LTPURPLE);
 fprintf(f, "<TR> <TD style='color:#%06X;'> BLACK:      </TD> "
            "<TD> Compatible with annotated pair, no substitutions.<BR>         </TD> </TR>",
            BLACK);
 fprintf(f, "<TR> <TD style='color:#%06X;'> BLUE:       </TD> "
            "<TD> Compatible with annotated pair, single substitution.<BR>      </TD> </TR>",
            BLUE);
 fprintf(f, "<TR> <TD style='color:#%06X;'> GREEN:      </TD> "
            "<TD> Compatible with annotated pair, double substitution.<BR>      </TD> </TR>",
            GREEN);
 fprintf(f, "<TR> <TD style='color:#%06X;'> RED:        </TD> "
            "<TD> Not compatible with annotated pair, single substitution. <BR> </TD> </TR>",
            RED);
 fprintf(f, "<TR> <TD style='color:#%06X;'> ORANGE:     </TD> "
            "<TD> Not compatible with annotated pair, double substitution. <BR> </TD> </TR>",
            ORANGE);
 fprintf(f, "<TR> <TD style='color:#%06X;'> MAGENTA:    </TD> "
            "<TD> Not compatible with annotated pair, involves gap. <BR>        </TD> </TR>",
            MAGENTA);
 fprintf(f, "</TABLE>");
 /* Score legend */
 fprintf(f, "<BR>SCORE:   min ");
 htmlColorPrintString(f, s, colorFormat, colors, 0);
 fprintf(f, " max");
 }
 
 struct mafAli *mafFromRnaSecStrItem(char *mafTrack, struct rnaSecStr *item)
 {
 struct mafAli *maf;
 maf = hgMafFrag(database, mafTrack, item->chrom, item->chromStart, item->chromEnd, item->strand[0], NULL, NULL);
 return maf;
 }
 
 void mafSortBySpeciesOrder(struct mafAli *maf, char *speciesOrder)
 /* Sort maf components by species. Excised from mafClick.c. */
 {
 int speciesCt;
 char *species[256];
 struct mafComp **newOrder, *mcThis;
 int i;
 int mcCount;
 
 mcCount = 0;
 speciesCt = chopLine(cloneString(speciesOrder), species);
 newOrder = needMem((speciesCt + 1) * sizeof (struct mafComp *));
 newOrder[mcCount++] = maf->components;
 
 for (i = 0; i < speciesCt; i++)
   {
     if ((mcThis = mafMayFindCompSpecies(maf, species[i], '.')) == NULL)
 	continue;
     newOrder[mcCount++] = mcThis;
   }
 
 maf->components = NULL;
 for (i = 0; i < mcCount; i++)
   {
     newOrder[i]->next = 0;
     slAddHead(&maf->components, newOrder[i]);
   }
 
 slReverse(&maf->components);
 }
 
 void htmlPrintSecStrEvofoldDrawing(FILE *f, struct rnaSecStr *item)
 {
 char fileName[512];
 struct dnaSeq *seq;
 seq = hChromSeq(database, item->chrom, item->chromStart, item->chromEnd);
 touppers(seq->dna);
 if (item->strand[0] == '-')
     reverseComplement(seq->dna, seq->size);
 memSwapChar(seq->dna, seq->size, 'T', 'U');
 
 safef(fileName, sizeof(fileName), "/gbdb/%s/evoFold/%s/%s.png",
        database, item->chrom, item->name);
 if (fileExists(fileName))
     {
     fprintf(f, "<center><h2> RNA secondary structure drawing </h2></center>");
     fprintf(f,"<B>");
 
     // Could consider to serve up all EvoFold .png files from our public server in the future
     // fprintf(f,"<IMG SRC=\"http://genome.ucsc.edu/evoFold/%s/%s/%s.png\" border = '2' "
     //           "ALT=\"ERROR: VARA plotting failed.\"</B><BR>",
     fprintf(f,"<IMG SRC=\"../evoFold/%s/%s/%s.png\" border = '2' ALT=\"ERROR: symlink to file not found.\"</B><BR>",
             database, item->chrom, item->name);
     fprintf(f,"</B>");
     }
 
 freeMem(seq);
 printf("<p>The UCSC Genome Browser mirror site at the Molecular Diagnostic Laboratory (MDL) at Aarhus University Hospital Skejby in Denmark offers a VARNA Java applet to view the above RNA structure with more options, ");
 printf("<A HREF=\"");
 printf("http://genome-mirror.moma.ki.au.dk/cgi-bin/hgc?db=%s&c=%s&l=%d&r=%d&o=%d&t=%d"
         "&g=evofold&i=%s",database, item->chrom, item->chromStart, item->chromEnd, 
         item->chromStart, item->chromEnd, cgiEncode(item->name)); 
         // c, l and r are needed because mirror may have no cart for us. Not actually used, however.
 printf("\" TARGET=_blank>%s</A>.", "click here to go to genome-mirror.moma.ki.au.dk");
 fprintf(f,"  <B><FONT COLOR = RED>NOTE:</FONT> some operating system/browser combinations require ");
 fprintf(f," the latest version of Java for this to work properly.</FONT></B></P>");
 }
 
 void htmlPrintSecStrEvofoldV2Drawing(FILE *f, struct rnaSecStr *item)
 {
 char fileName[512];
 struct dnaSeq *seq;
 seq = hChromSeq(database, item->chrom, item->chromStart, item->chromEnd);
 touppers(seq->dna);
 if (item->strand[0] == '-')
     reverseComplement(seq->dna, seq->size);
 memSwapChar(seq->dna, seq->size, 'T', 'U');
 
 safef(fileName, sizeof(fileName), "/gbdb/%s/evoFoldV2/%s/%s.png",
        database, item->chrom, item->name);
 if (fileExists(fileName))
     {
     fprintf(f, "<center><h2> RNA secondary structure drawing </h2></center>");
     fprintf(f,"<B>");
 
     // Could consider to serve up all EvoFold .png files from our public server in the future
     // fprintf(f,"<IMG SRC=\"http://genome.ucsc.edu/evoFold/%s/%s/%s.png\" border = '2' ALT=\"ERROR: VARA plotting failed.\"</B><BR>",
     fprintf(f,"<IMG SRC=\"../evoFoldV2/%s/%s/%s.png\" border = '2' ALT=\"ERROR:  symlink to file not found.\"</B><BR>",
             database, item->chrom, item->name);
     fprintf(f,"</B>");
     }
 
 freeMem(seq);
 printf("<p>The UCSC Genome Browser mirror site at the Molecular Diagnostic Laboratory (MDL) at Aarhus University Hospital Skejby in Denmark offers a VARNA Java applet to view the above RNA structure with more options, ");
 printf("<A HREF=\"");
 printf("http://genome-mirror.moma.ki.au.dk/cgi-bin/hgc?db=%s&c=%s&l=%d&r=%d&o=%d&t=%d"
         "&g=evofoldV2&i=%s", database, item->chrom, item->chromStart, item->chromEnd, 
         item->chromStart, item->chromEnd, cgiEncode(item->name));  
         // c, l and r are needed because mirror may have no cart for us. Not actually used, however.
 printf("\" TARGET=_blank>%s</A>.", "click here to go to genome-mirror.moma.ki.au.dk");
 fprintf(f," <B><FONT COLOR = RED>NOTE:</FONT> some operating system/browser combinations require ");
 fprintf(f," the latest version of Java for this to work properly.</FONT></B></P>");
 }
 
 void doRnaSecStr(struct trackDb *tdb, char *itemName)
 /* Handle click on rnaSecStr type elements. */
 {
 char *table = tdb->table;
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr;
 struct rnaSecStr *item;
 char extraWhere[256];
 char **row;
 int  rowOffset = 0;
 char *mafTrack = trackDbRequiredSetting(tdb, "mafTrack");
 int start = cartInt(cart, "o");
 struct mafAli *maf;
 char option[128];
 char *speciesOrder = NULL;
 
 /* print header */
 genericHeader(tdb, itemName);
 /* printRfamUrl(itemName); */
 genericBedClick(conn, tdb, itemName, start, 6);
 htmlHorizontalLine();
 
 /* get the rnaSecStr and maf from db */
 sprintf(extraWhere, "chromStart = %d and name = '%s'", start, itemName);
 sr   = hExtendedChromQuery(conn, table, seqName, extraWhere,  FALSE, NULL, &rowOffset);
 row  = sqlNextRow(sr);
 item = rnaSecStrLoad(row + rowOffset);
 maf  = mafFromRnaSecStrItem(mafTrack, item);
 
 /* order maf by species */
 safef(option, sizeof(option), "%s.speciesOrder", tdb->track);
 speciesOrder = cartUsualString(cart, option, NULL);
 if (speciesOrder == NULL)
   speciesOrder = trackDbSetting(tdb, "speciesOrder");
 if (speciesOrder)
   mafSortBySpeciesOrder(maf, speciesOrder);
 
 mafAndFoldHeader(stdout);
 htmlPrintMafAndFold(stdout, maf, item->secStr, item->conf, 100);
 
 mafAndFoldLegend(stdout);
 
 /* Draw structure for evoFold */
 if (sameWord(tdb->table, "evofold"))
     {
     htmlHorizontalLine();
     htmlPrintSecStrEvofoldDrawing(stdout, item);
     }
 
 /* Draw structure for evoFoldV2 */
 if (sameWord(tdb->table, "evofoldV2"))
     {
     htmlHorizontalLine();
     htmlPrintSecStrEvofoldV2Drawing(stdout, item);
     }
 
 /* track specific html */
 printTrackHtml(tdb);
 
 /* clean up */
 mafAliFree(&maf);
 rnaSecStrFree(&item);
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 }