From 85cebb59b6a3269be78767456b588aa76b7f295a Mon Sep 17 00:00:00 2001 From: Anton Nekrutenko Date: Mon, 10 Mar 2008 21:57:32 +0000 Subject: [PATCH] Bar chart tool for use with taxonomy tools. Requires gnuplot and gnuplot.py. Still needs interface testing --- static/images/bar_chart.png | Bin 0 -> 13071 bytes tools/plotting/bar_chart.py | 144 ++++++++++++ tools/plotting/bar_chart.xml | 51 +++++ tools/taxonomy/T2T/taxonomy2tree.c | 341 ++++++++++++++++++++++------- 4 files changed, 453 insertions(+), 83 deletions(-) create mode 100644 static/images/bar_chart.png create mode 100644 tools/plotting/bar_chart.py create mode 100644 tools/plotting/bar_chart.xml diff --git a/static/images/bar_chart.png b/static/images/bar_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..c4bb3ae9873321c7fafca791f406e633acac2299 GIT binary patch literal 13071 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 T{H+o#fpFoRqEx)()j$3XNj2<@ literal 0 HcmV?d00001 diff --git a/tools/plotting/bar_chart.py b/tools/plotting/bar_chart.py new file mode 100644 index 00000000000..855e9e25373 --- /dev/null +++ b/tools/plotting/bar_chart.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python2.4 + + +""" +histogram_gnuplot.py <ylabel> <yrange_min> <yrange_max> <grath_file> +a generic histogram builder based on gnuplot backend + + data_file - tab delimited file with data + xtic_column - column containing labels for x ticks [integer, 0 means no ticks] + column_list - comma separated list of columns to plot + title - title for the entire histrogram + ylabel - y axis label + yrange_max - minimal value at the y axis (integer) + yrange_max - maximal value at the y_axis (integer) + to set yrange to auto assign 0 to yrange_mmin and yrange_max + graph_file - file to write histogram image to + pdf_size - as X,Y pair in inches (e.g., 11,8 or 8,11 etc.) + + + This tool required gnuplot and gnuplot.py + +anton nekrutenko | anton@bx.psu.edu + +""" + + +from Numeric import * +import Gnuplot, Gnuplot.funcutils +import sys, string, tempfile, os + +def stop_err(msg): + sys.stderr.write(msg) + sys.exit() + +def main(tmpFileName): + skipped_lines_count = 0 + skipped_lines_index = [] + gf = open(tmpFileName, 'w') + + + try: + in_file = open( sys.argv[1], 'r' ) + xtic = int( sys.argv[2] ) + col_list = string.split( sys.argv[3],"," ) + title = 'set title "' + sys.argv[4] + '"' + ylabel = 'set ylabel "' + sys.argv[5] + '"' + ymin = sys.argv[6] + ymax = sys.argv[7] + img_file = sys.argv[8] + pdf_size = sys.argv[9] + except: + stop_err("Check arguments\n") + + try: + int( col_list[0] ) + except: + stop_err('You forgot to set columns for plotting\n') + + + for i, line in enumerate( in_file ): + valid = True + line = line.rstrip('\r\n') + if line and not line.startswith( '#' ): + row = [] + try: + fields = line.split( '\t' ) + for col in col_list: + row.append( str( float( fields[int(col)-1] ) ) ) + + except: + valid = False + skipped_lines_count += 1 + skipped_lines_index.append(i) + + else: + valid = False + skipped_lines_count += 1 + skipped_lines_index.append(i) + + if valid and xtic > 0: + row.append( fields[xtic-1] ) + elif valid and xtic == 0: + row.append( str( i ) ) + + if valid: + gf.write( '\t'.join( row ) ) + gf.write( '\n' ) + + if skipped_lines_count < i: + + #prepare 'using' clause of plot statement + + g_plot_command = ' '; + + #set the first column + if xtic > 0: + g_plot_command = "'%s' using 1:xticlabels(%s) ti 'Column %s', " % ( tmpFileName, str( len( row ) ), col_list[0] ) + #g_plot_command = "'%s' using 1:xticlabels(%s), " % ( tmpFileName, str( len( row ) ) ) + else: + g_plot_command = "'%s' using 1, " % ( tmpFileName ) + + #set subsequent columns + + for i in range(1,len(col_list)): + g_plot_command += "'%s' using %s t 'Column %s', " % ( tmpFileName, str(i+1), col_list[i] ) + #g_plot_command += "'%s' using %s, " % ( tmpFileName, str(i+1) ) + + g_plot_command = g_plot_command.rstrip(', ') + + yrange = 'set yrange [' + ymin + ":" + ymax + ']' + + try: + g = Gnuplot.Gnuplot() + g('reset') + g('set boxwidth 0.9 absolute') + g('set style fill solid 1.00 border -1') + g('set style histogram clustered gap 5 title offset character 0, 0, 0') + g('set xtics border in scale 1,0.5 nomirror rotate by 90 offset character 0, 0, 0') + g('set key invert reverse Left outside') + if xtic == 0: g('unset xtics') + g(title) + g(ylabel) + g_term = 'set terminal pdf size ' + pdf_size + g(g_term) + g_out = 'set output "' + img_file + '"' + if ymin != ymax: + g(yrange) + g(g_out) + g('set style data histograms') + g.plot(g_plot_command) + except: + stop_err("Gnuplot error: Data cannot be plotted") + else: + sys.stderr.write('Columns %s of your dataset do not contain valid numeric data' %sys.argv[3] ) + + if skipped_lines_count > 0: + sys.stderr.write('You dataset contains %d invalid lines starting with line#%d\n' % ( skipped_lines_count, skipped_lines_index[0] ) ) + + +if __name__ == "__main__": + gp_data_file = tempfile.NamedTemporaryFile('w') + #gp_f, gp_data_file = tempfile.mkstemp(suffix="gp", text=True) + main(gp_data_file.name) + diff --git a/tools/plotting/bar_chart.xml b/tools/plotting/bar_chart.xml new file mode 100644 index 00000000000..810d373ca3b --- /dev/null +++ b/tools/plotting/bar_chart.xml @@ -0,0 +1,51 @@ +<tool id="barchart_gnuplot" name="Bar chart"> + <description>for multiple columns</description> + <command interpreter="python2.4"> + #if $xtic.userSpecified == "Yes": #bar_chart.py $input $xtic.xticColumn $colList "$title" "$ylabel" $ymin $ymax $out_file1 "$pdf_size" + #else: #bar_chart.py $input 0 $colList "$title" "$ylabel" $ymin $ymax $out_file1 "$pdf_size" + #end if + </command> + <inputs> + <param name="input" type="data" format="tabular" label="Dataset" help="Query missing? See TIP below"/> + <conditional name="xtic"> + <param name="userSpecified" type="select" label="Use X Tick labels?" help="see example below"> + <option value="Yes">Yes</option> + <option value="No">No</option> + </param> + <when value="Yes"> + <param name="xticColumn" type="data_column" data_ref="input" numerical="False" label="Use this column for X Tick labels" /> + </when> + <when value="No"> + </when> + </conditional> + <param name="colList" label="Numerical columns" type="data_column" numerical="True" multiple="True" data_ref="input" help="Multi-select list - hold the appropriate key while clicking to select multiple columns" /> + <param name="title" type="text" size="30" value="Bar Chart" label="Plot title"/> + <param name="ylabel" type="text" size="30" value="V1" label="Label for Y axis"/> + <param name="ymin" type="integer" size="4" value="0" label="Minimal value on Y axis" help="set to 0 for autoscaling"/> + <param name="ymax" type="integer" size="4" value="0" label="Maximal value on Y axis" help="set to 0 for autoscaling"/> + <param name="pdf_size" type="select" label="Choose chart size (inches)" help="inch = 2.54 cm"> + <option value="11,8">Normal: 11 by 8</option> + <option value="5,3">Small: 5 by 3</option> + <option value="17,11">Large: 17 by 11</option> + <option value="8,11">Normal Flipped: 8 by 11</option> + <option value="3,5">Small Flipped: 3 by 5</option> + <option value="11,17">Large Flipped: 11 by 17</option> + </param> + </inputs> + <outputs> + <data format="pdf" name="out_file1" /> + </outputs> + <help> + +**What it does** + +This tool builds a bar chart on one or more columns. Suppose you have dataset like this one:: + + Gene1 10 15 Gene2 20 14 Gene3 67 45 Gene4 55 12 + +Graphing columns 2 and 3 while using column 1 for X Tick Labels will produce the following plot: + +.. image:: ../static/images/bar_chart.png + +</help> +</tool> diff --git a/tools/taxonomy/T2T/taxonomy2tree.c b/tools/taxonomy/T2T/taxonomy2tree.c index 203dbe72dfb..a60eda539ce 100644 --- a/tools/taxonomy/T2T/taxonomy2tree.c +++ b/tools/taxonomy/T2T/taxonomy2tree.c @@ -10,6 +10,7 @@ #define DEFAULT_STRING_ALLOC 16L #define NUMBER_OF_FIELDS 24 #define NUMBER_OF_TAX_FIELDS 22 +#define AVL_THRESHOLD 64 char *rankLabels [NUMBER_OF_TAX_FIELDS] = {"root" , @@ -44,6 +45,8 @@ void check_pointer (void*); char validTaxonNameChar[256]; +long currentLineID = 1; + /*---------------------------------------------------------------------------------------------------- */ struct avl_table * idTagAVL = NULL, @@ -70,6 +73,24 @@ struct vector vaLength; }; + + +/*---------------------------------------------------------------------------------------------------- */ + +void reportError (char * theMessage) +{ + fprintf (stderr, "\nERROR: %s\n", theMessage); + exit (1); +} + +/*---------------------------------------------------------------------------------------------------- */ + +void reportErrorLine (char * theMessage, long lineID) +{ + fprintf (stderr, "SKIPPED line %d: %s\n", lineID, theMessage); +} + + /*---------------------------------------------------------------------------------------------------- */ struct bufferedString *allocateNewString (void) @@ -238,9 +259,11 @@ struct treeNode struct treeNode * parent; long startIndex, hitCount, - length; + length + ,beenhere; struct vector * children; + struct avl_table* cachedChildren; } *globalTreeRoot; @@ -251,77 +274,201 @@ struct treeNode * allocateNewTreeNode (void) struct treeNode *newN = (struct treeNode*)malloc (sizeof (struct treeNode)); check_pointer (newN); newN->parent = NULL; - newN->startIndex = 0; - newN->length = 0; - newN->hitCount = 0; - newN->children = allocateNewVector(); + newN->startIndex = 0; + newN->length = 0; + newN->hitCount = 0; + newN->beenhere = 0; + newN->cachedChildren = NULL; + newN->children = allocateNewVector(); check_pointer (newN->children); return newN; } /*---------------------------------------------------------------------------------------------------- */ -struct treeNode * addAChild (struct treeNode* p, struct treeNode * c) + +int compare_tree_nodes (const void *avl_a, const void *avl_b, void * xtra) { - struct treeNode * c2 = NULL; - long i = 0; - for (; i<p->children->vLength; i++) - if (((struct treeNode**)p->children->vData)[i]->startIndex == c->startIndex) - break; - if (p->children->vLength == i) - { - if (c->parent && c->parent != p) - { - c2 = allocateNewTreeNode(); - c2->startIndex = c->startIndex; - c2->length = c->length; - c2->hitCount = 1; - c = c2; - } - appendValueToVector (p->children, (long)c); - c->parent = p; - } - return c; + long t1 = ((struct treeNode*)avl_a)->startIndex, + t2 = ((struct treeNode*)avl_b)->startIndex; + + if (t1 < t2) + return -1; + if (t1 > t2) + return 1; + + return 0; } /*---------------------------------------------------------------------------------------------------- */ void destroyTreeNode (struct treeNode* n) { + if (n->cachedChildren) + avl_destroy (n->cachedChildren, NULL); free (n->children); free (n); } +/*---------------------------------------------------------------------------------------------------- */ + +void printTreeNode (FILE* f, struct treeNode* n) +{ + long i = 0; + fprintf (f, "Node name: "); + if (n->startIndex>=0) + { + for (;i < n->length; i++) + fputc (globalNameBuffer->sData[n->startIndex + i], f); + } + else + fprintf (f, " empty node"); + fprintf (f, "\nHit count %d (backup %d)\n", n->hitCount, n->beenhere); +} + +/*---------------------------------------------------------------------------------------------------- */ + +void traverseCheck (struct treeNode* n, char first) +{ + long i = 0; + + if (!first && n->startIndex >= 0 && n->beenhere != n->hitCount) + { + printTreeNode (stderr, n); + //reportError ("DEATH AND DECAY, BIZNATCH!\n"); + } + + for (i = 0; i<n->children->vLength; i++) + traverseCheck (((struct treeNode**)n->children->vData)[i], first); + + if (first) + { + if (n->children->vLength == 0) + n->beenhere = n->hitCount; + + if (n->parent) + n->parent->beenhere += n->beenhere; + } +} + + /*---------------------------------------------------------------------------------------------------- */ void traverseTree (FILE *summaryFile, struct treeNode* n, long maxDepth, long currentDepth) { long i = 0; char c; + if (currentDepth <= maxDepth) { if (n->children->vLength && maxDepth > currentDepth) { - fputc ('(',summaryFile); - for (; i<n->children->vLength; i++) + if (n->startIndex < 0) { - traverseTree (summaryFile, ((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1); - if (i<n->children->vLength-1) - fputc (',',summaryFile); + for (i=0; i>n->startIndex && currentDepth - i < maxDepth; i--) + fputc ('(', summaryFile); + if (i == n->startIndex) + i = 0; } + else + fputc ('(',summaryFile); + + if (i==0) + for (; i<n->children->vLength; i++) + { + traverseTree (summaryFile, ((struct treeNode**)n->children->vData)[i], maxDepth, currentDepth+1); + if (i<n->children->vLength-1) + fputc (',',summaryFile); + } + + if (n->startIndex < 0) + for (i=0; i>n->startIndex+1 && currentDepth - i < maxDepth; i--) + fprintf (summaryFile,")n:%d", n->hitCount); fputc (')',summaryFile); } - for (i=n->startIndex; i<n->startIndex+n->length;i++) + + if (n->startIndex>= 0) { - c = globalNameBuffer->sData[i]; - if (validTaxonNameChar [c]) - fputc (c,summaryFile); - else - fputc ('_',summaryFile); + for (i=n->startIndex; i<n->startIndex+n->length;i++) + { + c = globalNameBuffer->sData[i]; + if (validTaxonNameChar [c]) + fputc (c,summaryFile); + else + fputc ('_',summaryFile); + } + fprintf (summaryFile,":%d", n->hitCount); } - fprintf (summaryFile,":%d", n->hitCount); + else + fprintf (summaryFile, "n:%d", n->hitCount); } } +/*---------------------------------------------------------------------------------------------------- */ +struct treeNode * addAChild (struct treeNode* p, struct treeNode * c, char killIfD) +{ + struct treeNode * c2 = NULL; + long i = 0; + char addNode = 0; + + if (p->cachedChildren) + { + if ((c2 = ((struct treeNode*)avl_find (p->cachedChildren, c))) == NULL) + addNode = 1; + /*else + { + if (c2->startIndex > globalNameBuffer->sLength || c2->startIndex < 0) + printf ("Reject node add %x %d %d\n", c2, c2->startIndex, c->startIndex); + }*/ + } + else + { + for (; i<p->children->vLength; i++) + if (((struct treeNode**)p->children->vData)[i]->startIndex == c->startIndex) + break; + addNode = (p->children->vLength == i); + } + + if (addNode) + { + if (c->parent && c->parent != p) + { + c2 = allocateNewTreeNode(); + c2->startIndex = c->startIndex; + c2->length = c->length; + c2->hitCount = 1; + //if (p->cachedChildren) + // fprintf (stdout, "%x %x\n", p, c->parent); + c = c2; + + } + c->parent = p; + appendValueToVector (p->children, (long)c); + if (p->children->vLength > AVL_THRESHOLD) + if (p->cachedChildren == NULL) + { + //fprintf (stdout, "Switch %d\n", currentLineID); + // switch over the the avl representation of nodes + p->cachedChildren = avl_create (compare_tree_nodes, NULL, NULL); + for (i=0; i<p->children->vLength; i++) + avl_probe(p->cachedChildren, ((struct node**)p->children->vData)[i]); + } + else + avl_probe (p->cachedChildren, c); + } + else + { + if (killIfD) + destroyTreeNode (c); + if (c2) + return c2; + else + c = ((struct treeNode**)p->children->vData)[i]; + + } + return c; +} + + /*---------------------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------------------- */ @@ -359,6 +506,7 @@ int compare_id_tags (const void *avl_a, const void *avl_b, void * xtra) return 0; } + /*---------------------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------------------- */ @@ -473,22 +621,6 @@ void destroy_string (struct bufferedString* aStr) } -/*---------------------------------------------------------------------------------------------------- */ - -void reportError (char * theMessage) -{ - fprintf (stderr, "\nERROR: %s\n", theMessage); - exit (1); -} - -/*---------------------------------------------------------------------------------------------------- */ - -void reportErrorLine (char * theMessage, long lineID) -{ - fprintf (stderr, "SKIPPED line %d: %s\n", lineID, theMessage); -} - - /*---------------------------------------------------------------------------------------------------- */ int main (int argc, const char * argv[]) @@ -507,23 +639,24 @@ int main (int argc, const char * argv[]) struct treeNode *currentParent = NULL, *currentNode; - + char automatonState = 0, currentField = 0, currentChar = 0, showEmptyNodes = 0; - long currentLineID = 1, - expectedFields = NUMBER_OF_FIELDS, + long expectedFields = NUMBER_OF_FIELDS, indexer, indexer2, indexer3, - maxTreeLevel = 0; + maxTreeLevel = 0, + setEOF = 0, + nRunCounter = 0; FILE * treeFile = NULL, * summaryFile = NULL, * inFile = NULL; - + globalNameBuffer = allocateNewString(); globalTreeRoot = allocateNewTreeNode(); currentBuffers = (struct bufferedString**)malloc (expectedFields*sizeof (struct bufferedString*)); @@ -571,7 +704,7 @@ int main (int argc, const char * argv[]) currentChar = fgetc(inFile); currentField = 0; - while (!feof(inFile)) + while (setEOF < 2) { switch (automatonState) { @@ -591,33 +724,35 @@ int main (int argc, const char * argv[]) break; case 1: /* reading sequence ID */ - if (isalnum(currentChar)) - appendCharacterToString(currentBuffers[currentField],toupper(currentChar)); + if (currentChar == '\t') + { + automatonState = 2; + continue; + } else - if (currentChar == '\t') - { - automatonState = 2; - continue; - } - else + { + if (currentChar == '\n' || currentChar == '\r') { reportErrorLine ("Expected a tab following the gid",currentLineID); automatonState = 6; continue; } - break; + else + appendCharacterToString(currentBuffers[currentField],toupper(currentChar)); + + } + break; case 2: /* looking for a \t or a \n|\r*/ if (currentChar == '\t') { - automatonState = 3; currentField ++; - if (currentField == expectedFields) - { - reportErrorLine ("Too many fields",currentLineID); - automatonState = 6; - continue; - } + if (currentField < expectedFields) + automatonState = 3; + + //reportErrorLine ("Too many fields",currentLineID); + //automatonState = 6; + //continue; } else if (currentChar == '\n' || currentChar == '\r') @@ -628,14 +763,19 @@ int main (int argc, const char * argv[]) aTag->taxID = atoi (currentBuffers[1]->sData); aTag->hit_count = 1; aTag2 = *(struct storedIDTag**)avl_probe(idTagAVL, aTag); + //fprintf (stdout, "%d %d %x %x\n", currentLineID,aTag->taxID,aTag,aTag2); if (aTag == aTag2) // new taxID { // process fields currentParent = globalTreeRoot; + nRunCounter = 0; for (indexer = NUMBER_OF_FIELDS-NUMBER_OF_TAX_FIELDS; indexer < NUMBER_OF_FIELDS; indexer++) { indexer2 = strlen(currentBuffers[indexer]->sData); - if ((currentBuffers[indexer])->sData[0] != 'n' || indexer2 > 1 || showEmptyNodes && indexer2 > 0) // not 'n' + //fprintf (stdout, "%d %d\n", indexer, nRunCounter,indexer2); + if ((currentBuffers[indexer])->sData[0] == 'n' && indexer2 == 1) + nRunCounter++; + else { indexer3 = globalNameBuffer->sLength; appendRangeToString (globalNameBuffer,currentBuffers[indexer],0,indexer2-1); @@ -654,6 +794,7 @@ int main (int argc, const char * argv[]) if (sTag == sTag3) // new node { //fprintf (stderr, "Add node level %d %d\n",indexer-(NUMBER_OF_FIELDS-NUMBER_OF_TAX_FIELDS), sTag2->startIndex); + sTag3 = sTag; sTag3->refNode = allocateNewTreeNode(); sTag3->refNode->length = sTag2->length; sTag3->refNode->startIndex = sTag2->startIndex; @@ -665,14 +806,38 @@ int main (int argc, const char * argv[]) sTag3->refNode->hitCount++; + if (showEmptyNodes && nRunCounter>0) + { + currentNode = allocateNewTreeNode(); + currentNode->startIndex = -nRunCounter; + currentNode->hitCount = 1; + if (currentParent) + currentParent = addAChild (currentParent,currentNode,1); + else + reportError ("Attempting to attach an empty node a null parent."); + } + if (currentParent) - currentParent = addAChild (currentParent,sTag3->refNode); + currentParent = addAChild (currentParent,sTag3->refNode,0); else currentParent = sTag3->refNode; + + nRunCounter = 0; } } + if (nRunCounter>0) + { + currentNode = allocateNewTreeNode(); + currentNode->startIndex = -nRunCounter; + currentNode->hitCount = 1; + if (currentParent) + currentParent = addAChild (currentParent,currentNode,1); + else + reportError ("Attempting to attach an empty node a null parent."); + } aTag->tNode = currentParent; aTag = allocateIDTag(); + } else { @@ -683,17 +848,20 @@ int main (int argc, const char * argv[]) currentParent->hitCount++; currentParent = currentParent->parent; } - + //printf ("Duplicate tag %d %d\n", aTag2->hit_count, aTag2->taxID); } - + //traverseCheck (globalTreeRoot); automatonState = 5; continue; } else { - reportErrorLine ("Expected a tab following a field",currentLineID); - automatonState = 6; - continue; + if (currentField < expectedFields) + { + reportErrorLine ("Expected a tab following a field",currentLineID); + automatonState = 6; + continue; + } } break; @@ -746,8 +914,13 @@ int main (int argc, const char * argv[]) break; } currentChar = fgetc(inFile); + if (feof (inFile)) + { + setEOF ++; + currentChar = '\n'; + } } - + fprintf (stderr, "Read %d unique taxIDs\n", avl_count (idTagAVL)); fclose (inFile); @@ -781,6 +954,8 @@ int main (int argc, const char * argv[]) traverseTree (treeFile,((struct treeNode**)globalTreeRoot->children->vData)[0],(maxTreeLevel>0)?(maxTreeLevel+1):0xfffffL,0); fclose (treeFile); + traverseCheck (((struct treeNode**)globalTreeRoot->children->vData)[0], 1); + traverseCheck (((struct treeNode**)globalTreeRoot->children->vData)[0], 0); return 0; }