]> git.donarmstrong.com Git - mothur.git/blob - heatmap.cpp
modified calculators to use doubles, added numotu and fontsize parameters to heatmap...
[mothur.git] / heatmap.cpp
1 /*
2  *  heatmap.cpp
3  *  Mothur
4  *
5  *  Created by Sarah Westcott on 3/25/09.
6  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
7  *
8  */
9
10 #include "heatmap.h"
11
12 //**********************************************************************************************************************
13 HeatMap::HeatMap(string sort, string scale, int num, int fsize, string dir){
14         try {
15                 globaldata = GlobalData::getInstance();
16                 m = MothurOut::getInstance();
17 //              format = globaldata->getFormat();
18                 sorted = sort;
19                 scaler = scale;
20                 outputDir = dir;
21                 numOTU = num;
22                 fontSize = fsize;
23         }
24         catch(exception& e) {
25                 m->errorOut(e, "HeatMap", "HeatMap");
26                 exit(1);
27         }
28 }
29
30 //**********************************************************************************************************************
31
32 string HeatMap::getPic(RAbundVector* rabund) {
33         try {
34                 
35                 
36                 float maxRelAbund = 0.0;                
37                 
38                 for(int i=0;i<rabund->size();i++){                              
39                         float relAbund = rabund->get(i) / (float)rabund->getNumSeqs();
40                         if(relAbund > maxRelAbund){     maxRelAbund = relAbund; }
41                 }
42                 
43                 
44                 vector<string> scaleRelAbund(rabund->size(), "");
45                 
46                 for(int i=0;i<rabund->size();i++){
47                         float relAbund = rabund->get(i) / (float)rabund->getNumSeqs();
48                         
49                         if (m->control_pressed) { return "control"; }
50                         
51                         if (rabund->get(i) != 0) { //don't want log value of 0.
52                                 if (scaler == "log10") {
53                                         scaleRelAbund[i] = toHex(int(255 * log10(relAbund) / log10(maxRelAbund))) + "0000";  
54                                 }else if (scaler == "log2") {
55                                         scaleRelAbund[i] = toHex(int(255 * log2(relAbund) / log2(maxRelAbund))) + "0000";  
56                                 }else if (scaler == "linear") {
57                                         scaleRelAbund[i] = toHex(int(255 * relAbund / maxRelAbund)) + "0000";  
58                                 }else {  //if user enters invalid scaler option.
59                                         scaleRelAbund[i] = toHex(int(255 * log10(relAbund / log10(maxRelAbund))))  + "0000"; 
60                                 } 
61                         }
62                         else { scaleRelAbund[i] = "FFFFFF";  }
63                 }
64                 
65                 
66                 string filenamesvg = outputDir + getRootName(getSimpleName(globaldata->inputFileName)) + rabund->getLabel() + ".heatmap.bin.svg";
67                 openOutputFile(filenamesvg, outsvg);
68                 
69                 //svg image
70                 outsvg << "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 " + toString(300) + " " + toString((rabund->getNumBins()*5 + 120))  + "\">\n";
71                 outsvg << "<g>\n";
72                 
73                 //white backround
74                 outsvg << "<rect fill=\"white\" stroke=\"white\" x=\"0\" y=\"0\" width=\"" + toString(300) + "\" height=\"" + toString((rabund->getNumBins()*5 + 120))  + "\"/>"; 
75                 outsvg << "<text fill=\"black\" class=\"seri\" font-size=\"" + toString(fontSize) + "\" x=\"" + toString((150) - 40) + "\" y=\"25\">Heatmap at distance " + rabund->getLabel() + "</text>\n";
76                                 
77                 //output legend and color labels
78                 string color;
79                 int x = 0;
80                 int y = 103 + (rabund->getNumBins()*5);
81                 printLegend(y, maxRelAbund);
82                 
83                 y = 70;
84                 for (int i = 0; i < scaleRelAbund.size(); i++) {
85                         if (m->control_pressed) { outsvg.close(); return "control"; }
86                         
87                         outsvg << "<rect fill=\"#" + scaleRelAbund[i] + "\" stroke=\"#" + scaleRelAbund[i] + "\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"300\" height=\"5\"/>\n";
88                         y += 5;
89                 }
90                 
91                 outsvg << "</g>\n</svg>\n";
92                 outsvg.close();
93                 
94                 return filenamesvg;
95         }
96         catch(exception& e) {
97                 m->errorOut(e, "HeatMap", "getPic");
98                 exit(1);
99         }
100 }
101
102 //**********************************************************************************************************************
103
104 string HeatMap::getPic(vector<SharedRAbundVector*> lookup) {
105         try {
106         
107                 int numBinsToDisplay = lookup[0]->size();
108                 
109                 if (numOTU != 0) { //user want to display a portion of the otus
110                         if (numOTU < numBinsToDisplay) {  numBinsToDisplay = numOTU; }
111                 }
112                 
113                 //sort lookup so shared bins are on top
114                 if (sorted != "none") {  sortSharedVectors(lookup);  }
115                 
116                 vector<vector<string> > scaleRelAbund;
117                 vector<float> maxRelAbund(lookup.size(), 0.0);          
118                 float superMaxRelAbund = 0;
119                 
120                 for(int i = 0; i < lookup.size(); i++){
121                         for(int j=0; j<lookup[i]->size(); j++){
122                                 
123                                 float relAbund = lookup[i]->getAbundance(j) / (float)lookup[i]->getNumSeqs();
124                                 if(relAbund > maxRelAbund[i]){  maxRelAbund[i] = relAbund;      }
125                         }
126                         if(maxRelAbund[i] > superMaxRelAbund){  superMaxRelAbund = maxRelAbund[i];      }
127                 }
128                 
129                 scaleRelAbund.resize(lookup.size());
130                 for(int i=0;i<lookup.size();i++){
131                         scaleRelAbund[i].assign(lookup[i]->size(), "");
132                         for(int j=0;j<lookup[i]->size();j++){
133                                 if (m->control_pressed) {  return "control"; }
134                                 float relAbund = lookup[i]->getAbundance(j) / (float)lookup[i]->getNumSeqs();
135                                 
136                                 if (lookup[i]->getAbundance(j) != 0) { //don't want log value of 0.
137                                         if (scaler == "log10") {
138                                                 scaleRelAbund[i][j] = toHex(int(255 * log10(relAbund) / log10(maxRelAbund[i]))) + "0000";  
139                                         }else if (scaler == "log2") {
140                                                 scaleRelAbund[i][j] = toHex(int(255 * log2(relAbund) / log2(maxRelAbund[i]))) + "0000";  
141                                         }else if (scaler == "linear") {
142                                                 scaleRelAbund[i][j] = toHex(int(255 * relAbund / maxRelAbund[i])) + "0000";  
143                                         }else {  //if user enters invalid scaler option.
144                                                 scaleRelAbund[i][j] = toHex(int(255 * log10(relAbund / log10(maxRelAbund[i]))))  + "0000"; 
145                                         } 
146                                 }else { scaleRelAbund[i][j] = "FFFFFF";  }
147
148                         }
149                 }
150
151                 string filenamesvg = outputDir + getRootName(getSimpleName(globaldata->inputFileName)) + lookup[0]->getLabel() + ".heatmap.bin.svg";
152                 openOutputFile(filenamesvg, outsvg);
153                 
154                 //svg image
155                 outsvg << "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 " + toString(lookup.size() * 300) + " " + toString((lookup[0]->getNumBins()*5 + 120))  + "\">\n";
156                 outsvg << "<g>\n";
157                 
158                 //white backround
159                 outsvg << "<rect fill=\"white\" stroke=\"white\" x=\"0\" y=\"0\" width=\"" + toString(lookup.size() * 300) + "\" height=\"" + toString((lookup[0]->getNumBins()*5 + 120))  + "\"/>"; 
160                 outsvg << "<text fill=\"black\" class=\"seri\" font-size=\"" + toString(fontSize) + "\" text-anchor=\"middle\" x=\"" + toString((lookup.size() * 150) - 40) + "\" y=\"25\">Heatmap at distance " + lookup[0]->getLabel() + "</text>\n";
161                 
162                 //column labels
163                 for (int h = 0; h < lookup.size(); h++) {
164                         outsvg << "<text fill=\"black\" class=\"seri\" font-size=\"" + toString(fontSize) + "\" x=\"" + toString(((300 * (h+1)) - 150) - ((int)lookup[h]->getGroup().length() / 2)) + "\" y=\"50\">" + lookup[h]->getGroup() + "</text>\n"; 
165                 }
166
167                 //output legend and color labels
168                 string color;
169                 int x = 0;
170                 int y = 103 + (lookup[0]->getNumBins()*5);
171                 printLegend(y, superMaxRelAbund);
172                 
173                 y = 70;
174                 for (int i = 0; i < numBinsToDisplay; i++) {
175                         for (int j = 0; j < scaleRelAbund.size(); j++) {
176                                 if (m->control_pressed) { outsvg.close(); return "control"; }
177                                 
178                                 outsvg << "<rect fill=\"#" + scaleRelAbund[j][i] + "\" stroke=\"#" + scaleRelAbund[j][i] + "\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"300\" height=\"5\"/>\n";
179                                 x += 300;
180                         }
181                         x = 0;
182                         y += 5;
183                 }
184                 
185                 outsvg << "</g>\n</svg>\n";
186                 outsvg.close();
187                 
188                 return filenamesvg;
189
190         }
191         catch(exception& e) {
192                 m->errorOut(e, "HeatMap", "getPic");
193                 exit(1);
194         }
195 }
196
197 //**********************************************************************************************************************
198 int HeatMap::sortSharedVectors(vector<SharedRAbundVector*>& lookup){
199         try {
200                                 
201                 vector<SharedRAbundVector*> looktemp;
202                 map<int, int> place; //spot in lookup where you insert shared by, ie, 3 -> 2 if they are shared by 3 inset into location 2.
203                 map<int, int>::iterator it;
204                 
205                 /****************** find order of otus **********************/
206                 if (sorted == "shared") {
207                         place = orderShared(lookup);    
208                 }else if (sorted == "topotu") {
209                         place = orderTopOtu(lookup);    
210                 }else if (sorted == "topgroup") {
211                         place = orderTopGroup(lookup);  
212                 }else { m->mothurOut("Error: invalid sort option."); m->mothurOutEndLine();  return 1; }
213                                 
214                 
215                 /******************* create copy of lookup *********************/
216                 //create and initialize looktemp as a copy of lookup
217                 for (int i = 0; i < lookup.size(); i++) { 
218                         SharedRAbundVector* temp = new SharedRAbundVector(lookup[i]->getNumBins());
219                         temp->setLabel(lookup[i]->getLabel());
220                         temp->setGroup(lookup[i]->getGroup());
221                         //copy lookup i's info
222                         for (int j = 0; j < lookup[i]->size(); j++) {
223                                 temp->set(j, lookup[i]->getAbundance(j), lookup[i]->getGroup());
224                         }
225                         looktemp.push_back(temp);
226                 }
227         
228                 /************************ fill lookup in order given by place *********************/
229                 //for each bin
230                 for (int i = 0; i < looktemp[0]->size(); i++) {                                                                                                         //place
231                         //fill lookup                                                                                                                                                                   // 2 -> 1
232                         for (int j = 0; j < looktemp.size(); j++) {                                                                                                             // 3 -> 2
233                                 int newAbund = looktemp[j]->getAbundance(i);                                                                                            // 1 -> 3
234                                 lookup[j]->set(place[i], newAbund, looktemp[j]->getGroup()); //binNumber, abundance, group
235                         }
236                 }
237                 
238                 //delete looktemp -- Sarah look at - this is causing segmentation faults
239                 for (int j = 0; j < looktemp.size(); j++) {
240 //                      delete looktemp[j];
241                 }
242                 
243                 return 0;
244                 
245         }
246         catch(exception& e) {
247                 m->errorOut(e, "HeatMap", "sortSharedVectors");
248                 exit(1);
249         }
250 }
251 //**********************************************************************************************************************
252 map<int, int> HeatMap::orderShared(vector<SharedRAbundVector*>& lookup){
253         try {
254                                 
255                 map<int, int> place; //spot in lookup where you insert shared by, ie, 3 -> 2 if they are shared by 3 inset into location 2.
256                 map<int, int>::iterator it;
257                 
258                 vector<int> sharedBins;
259                 vector<int> uniqueBins;
260                 
261                 //for each bin
262                 for (int i = 0; i < lookup[0]->size(); i++) {   
263                         int count = 0;                                                                                          
264                         
265                         //is this bin shared
266                         for (int j = 0; j < lookup.size(); j++) {               if (lookup[j]->getAbundance(i) != 0) { count++; }       }
267                         
268                         if (count < 2)  {  uniqueBins.push_back(i); }
269                         else                    {  sharedBins.push_back(i); }
270                 }
271                 
272                 //fill place
273                 for (int i = 0; i < sharedBins.size(); i++) { place[sharedBins[i]] = i; }
274                 for (int i = 0; i < uniqueBins.size(); i++) { place[uniqueBins[i]] = (sharedBins.size() + i); }
275                 
276                 return place;
277                 
278         }
279         catch(exception& e) {
280                 m->errorOut(e, "HeatMap", "orderShared");
281                 exit(1);
282         }
283 }
284 //**********************************************************************************************************************
285 map<int, int> HeatMap::orderTopOtu(vector<SharedRAbundVector*>& lookup){
286         try {
287                                 
288                 map<int, int> place; //spot in lookup where you insert shared by, ie, 3 -> 2 if they are shared by 3 inset into location 2.
289                 map<int, int>::iterator it;
290                 
291                 vector<binCount> totals;
292                 
293                 //for each bin
294                 for (int i = 0; i < lookup[0]->size(); i++) {   
295                         int total = 0;                                                                                          
296                         
297                         for (int j = 0; j < lookup.size(); j++) {       total += lookup[j]->getAbundance(i);    }
298                         
299                         binCount temp(i, total);
300                         
301                         totals.push_back(temp);
302                 }
303                 
304                 sort(totals.begin(), totals.end(), comparebinCounts);
305                 
306                 //fill place
307                 for (int i = 0; i < totals.size(); i++) {   place[totals[i].bin] = i;  }
308                                 
309                 return place;
310                 
311         }
312         catch(exception& e) {
313                 m->errorOut(e, "HeatMap", "orderTopOtu");
314                 exit(1);
315         }
316 }
317 //**********************************************************************************************************************
318 map<int, int> HeatMap::orderTopGroup(vector<SharedRAbundVector*>& lookup){
319         try {
320                                 
321                 map<int, int> place; //spot in lookup where you insert shared by, ie, 3 -> 2 if they are shared by 3 inset into location 2.
322                 map<int, int>::iterator it;
323                 
324                 vector < vector<binCount> > totals; //totals[0] = bin totals for group 0, totals[1] = bin totals for group 1, ...
325                 totals.resize(lookup.size());
326                 
327                 //for each bin
328                 for (int i = 0; i < lookup[0]->size(); i++) {   
329                         for (int j = 0; j < lookup.size(); j++) {
330                                 binCount temp(i, (lookup[j]->getAbundance(i)));
331                                 totals[j].push_back(temp);
332                         }
333                 }
334                 
335                 for (int i = 0; i < totals.size(); i++) { sort(totals[i].begin(), totals[i].end(), comparebinCounts);  }
336                 
337                 //fill place
338                 //grab the top otu for each group adding it if its not already added
339                 int count = 0;
340                 for (int i = 0; i < totals[0].size(); i++) { 
341                 
342                         for (int j = 0; j < totals.size(); j++) {  
343                                 it = place.find(totals[j][i].bin);
344                                 
345                                 if (it == place.end()) { //not added yet
346                                         place[totals[j][i].bin] = count;
347                                         count++;
348                                 }
349                         }
350                 }
351                                 
352                 return place;
353                 
354         }
355         catch(exception& e) {
356                 m->errorOut(e, "HeatMap", "orderTopGroup");
357                 exit(1);
358         }
359 }
360 //**********************************************************************************************************************
361
362 void HeatMap::printLegend(int y, float maxbin) {
363         try {
364                 
365                 //output legend and color labels
366                 //go through map and give each score a color value
367                 string color;
368                 int x = 10;
369                 
370                 //prints legend
371                 for (int i = 1; i < 255; i++) {
372                         color = toHex(int((float)(i)));
373                         outsvg << "<rect fill=\"#" + color + "0000\" stroke=\"#" + color + "0000\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"1\" height=\"10\"/>\n";
374                         x += 1;
375                 }
376                 
377                 //prints legend labels
378                 x = 10;
379                 for (int i = 1; i<=5; i++) {
380                         float label;
381                         if(scaler== "log10")            {       label = maxbin * log10(51*i) / log10(255);      }
382                         else if(scaler== "log2")        {       label = maxbin * log2(51*i) / log2(255);        }
383                         else if(scaler== "linear")      {       label = maxbin * 51 * i / 255;                          }
384                         else                                            {       label = maxbin * log10(51*i) / log10(255);      }
385                         label = int(label * 1000 + 0.5);
386                         label /= 1000.0;
387                         string text = toString(label, 3);
388                         
389                         outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString(x) + "\" y=\"" + toString(y-3) + "\">" + text + "</text>\n";
390                         x += 60;
391                 }
392         }
393         
394         catch(exception& e) {
395                 m->errorOut(e, "HeatMap", "printLegend");
396                 exit(1);
397         }
398 }
399 //**********************************************************************************************************************
400
401
402
403
404