533112afe2a2005e80cdb1f82904ea65032d4302 braney Sat Oct 2 11:37:34 2021 -0700 split hg/lib into two separate libaries, one only used by the cgis diff --git src/hg/cgilib/hgExp.c src/hg/cgilib/hgExp.c new file mode 100644 index 0000000..863463c --- /dev/null +++ src/hg/cgilib/hgExp.c @@ -0,0 +1,328 @@ +/* hgExp - help browse expression data. */ + +/* Copyright (C) 2014 The Regents of the University of California + * See README in this or parent directory for licensing information. */ + +#include "common.h" +#include "hash.h" +#include "jksql.h" +#include "hdb.h" +#include "gifLabel.h" +#include "cart.h" +#include "cheapcgi.h" +#include "hgExp.h" +#include "portable.h" + + +static int expSubcellWidth = 21; + +static char *colorSchemeVals[] = { +/* Menu option for color scheme. */ + "red high/green low", + "yellow high/blue low", +}; + +void hgExpColorDropDown(struct cart *cart, char *varName) +/* Make color drop-down. */ +{ +char *checked = cartUsualString(cart, varName, colorSchemeVals[0]); +cgiMakeDropList(varName, + colorSchemeVals, ArraySize(colorSchemeVals), checked); +} + +boolean hgExpRatioUseBlue(struct cart *cart, char *varName) +/* Return TRUE if should use blue instead of red + * in the expression ratios. */ +{ +char *val = cartUsualString(cart, varName, colorSchemeVals[0]); +return !sameString(val, colorSchemeVals[0]); +} + +char **hgExpGetNames(char *database, char *table, + int expCount, int *expIds, int skipSize) +/* Create array filled with experiment names. */ +{ +char **names, *name; +int i; +char *db = database; +struct sqlConnection *conn; +char query[256], nameBuf[128]; +int maxLen = 0, len; + +if (!hTableExists(database, table)) + db = "hgFixed"; +conn = sqlConnect(db); +/* Read into array and figure out longest name. */ +AllocArray(names, expCount); +for (i=0; i<expCount; ++i) + { + int ix = expIds[i]; + if (ix == -1) + names[i] = NULL; + else + { + sqlSafef(query, sizeof(query), "select name from %s where id = %d", + table, expIds[i]); + if ((name = sqlQuickQuery(conn, query, nameBuf, sizeof(nameBuf))) == NULL) + name = "unknown"; + else + name += skipSize; + names[i] = cloneString(name); + len = strlen(name); + if (len > maxLen) maxLen = len; + } + } +sqlDisconnect(&conn); + +/* Right justify names. */ +for (i=0; i<expCount; ++i) + { + char *name = names[i]; + if (name != NULL) + { + safef(nameBuf, sizeof(nameBuf), "%*s", maxLen, name); + freeMem(name); + names[i] = cloneString(nameBuf); + } + } +return names; +} + +static int countNonNull(char **row, int maxCount) +/* Count number of non-null rows. */ +{ +int i; +for (i=0; i<maxCount; ++i) + { + if (row[i] == NULL) + break; + } +return i; +} + +void hgExpLabelPrint(char *database, char *colName, char *subName, int skipName, + char *url, int representativeCount, int *representatives, + char *expTable, int gifStart) +/* Print out labels of various experiments. */ +{ +int i; +int groupSize; +char gifName[128]; +char **experiments = hgExpGetNames(database, + expTable, representativeCount, representatives, skipName); +int height = gifLabelMaxWidth(experiments, representativeCount); + +for (i=0; i<representativeCount; i += groupSize+1) + { + printf("<TD VALIGN='BOTTOM' WIDTH=%d>", expSubcellWidth); + groupSize = countNonNull(experiments+i, representativeCount-i); + safef(gifName, sizeof(gifName), "../trash/nea_%s_%s%d.png", + colName, subName, ++gifStart); + gifLabelVerticalText(gifName, experiments+i, groupSize, height); + if (url != NULL) + printf("<A HREF=\"%s\">", url); + printf("<IMG BORDER=0 SRC=\"%s\">", gifName); + if (url != NULL) + printf("</A>"); + printf("</TD>"); + } + +/* Clean up */ +for (i=0; i<representativeCount; ++i) + freeMem(experiments[i]); +freeMem(experiments); +} + + +boolean hgExpLoadVals(struct sqlConnection *lookupConn, + struct sqlConnection *dataConn, + char *lookupTable, char *name, char *dataTable, + int *retValCount, float **retVals) +/* Load up and return expression bed record. Return NULL + * if none of given name exist. */ +{ +char query[256]; +char expName[64]; +struct sqlResult *sr; +char **row; +boolean ok = FALSE; +if (lookupTable != NULL && !sameWord(lookupTable, "null")) + { + sqlSafef(query, sizeof(query), "select value from %s where name = '%s'", + lookupTable, name); + if (sqlQuickQuery(lookupConn, query, expName, sizeof(expName)) == NULL) + return FALSE; + sqlSafef(query, sizeof(query), "select expScores from %s where name = '%s'", + dataTable, expName); + } +else + sqlSafef(query, sizeof(query), "select expScores from %s where name = '%s'", + dataTable, name); +sr = sqlGetResult(dataConn, query); +if ((row = sqlNextRow(sr)) != NULL) + { + sqlFloatDynamicArray(row[0], retVals, retValCount); + ok = TRUE; + } +sqlFreeResult(&sr); +return ok; +} + + +static void hexOne(double val) +/* Convert val 0.0-1.0 to hex 00 to FF */ +{ +int hex = val * 0xFF; +if (hex > 0xFF) hex = 0xFF; +printf("%02X", hex); +} + +static void colorVal(double val, double scale, boolean useBlue, boolean useGrays, boolean logGrays) +/* Val is -1.0 to 1.0. Print color in form #FF0000, normally + * using green for minus values, red for plus values, but + * optionally using blue for minus values and yellow for plus values. */ +{ +if (useGrays) + { + if (val < 1) + printf("000000"); + else + { + val = (logGrays) ? log(val) * scale : val * scale; + hexOne(val); + hexOne(val); + hexOne(val); + } + } +else + { + val *= scale; + if (useBlue) + { + if (val < 0) + { + val = -val; + printf("00"); + printf("00"); + hexOne(val); + } + else + { + val *= 0.7; + hexOne(val); /* Red */ + hexOne(val); /* Green */ + printf("00"); /* Blue */ + } + } + else + { + if (val < 0) + { + printf("00"); /* Red */ + hexOne(-val*0.8); /* Green - brighter than red*/ + printf("00"); /* Blue */ + } + else + { + hexOne(val); + printf("00"); + printf("00"); + } + } + } +} + +static void startExpCell() +/* Print out start of expression cell, which contains a table. */ +{ +printf("<TD><TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0><TR>"); +} + +static void endExpCell() +/* Print out end of expression cell, closing up internal table. */ +{ +printf("</TR></TABLE></TD>"); +} + +static void restartExpCell() +/* End expression cell and begin a new one. */ +{ +endExpCell(); +startExpCell(); +} + +static void printRatioShades(char *colName, int repCount, + int *reps, int valCount, float *vals, + boolean colorBlindColors, + boolean useGrays, boolean logGrays, float scale) +/* Print out representatives in shades of color in table background. */ +{ +int i; +float val; +startExpCell(); +for (i=0; i<repCount; ++i) + { + int ix = reps[i]; + if (ix > valCount) + errAbort("Representative larger than biggest experiment in %s", colName); + if (ix == -1) + { + restartExpCell(); + } + else + { + val = vals[ix]; + if (val <= -9999) + printf("<TD WIDTH=%d> </TD>", expSubcellWidth); + else + { + printf("<TD WIDTH=%d BGCOLOR='#", expSubcellWidth); + colorVal(val, scale, colorBlindColors, useGrays, logGrays); + printf("'> </TD>"); + } + } + } +endExpCell(); +} + +static void replicate(char *s, int repCount, int *reps) +/* Replicate s in cells of table */ +{ +int i; +startExpCell(); +printf("%s", s); +for (i=0; i<repCount; ++i) + { + int ix = reps[i]; + if (ix == -1) + { + restartExpCell(); + printf("%s", s); + } + } +endExpCell(); +} + +void hgExpCellPrint(char *colName, char *geneId, + struct sqlConnection *lookupConn, char *lookupTable, + struct sqlConnection *dataConn, char *dataTable, + int representativeCount, int *representatives, + boolean useBlue, boolean useGrays, boolean logGrays, float scale) +/* Print out html for expression cell in table. */ +{ +int valCount; +float *vals = NULL; + +if (hgExpLoadVals(lookupConn, dataConn, lookupTable, geneId, dataTable, + &valCount, &vals)) + { + printRatioShades(colName, representativeCount, representatives, + valCount, vals, useBlue, useGrays, logGrays, scale); + freez(&vals); + } +else + { + replicate("<TD>n/a</TD>", representativeCount, representatives); + } +} +