]> git.donarmstrong.com Git - mothur.git/blob - heatmap.cpp
created mothurOut class to handle logfiles
[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, 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         }
22         catch(exception& e) {
23                 m->errorOut(e, "HeatMap", "HeatMap");
24                 exit(1);
25         }
26 }
27
28 //**********************************************************************************************************************
29
30 string HeatMap::getPic(RAbundVector* rabund) {
31         try {
32                 
33                 
34                 float maxRelAbund = 0.0;                
35                 
36                 for(int i=0;i<rabund->size();i++){                              
37                         float relAbund = rabund->get(i) / (float)rabund->getNumSeqs();
38                         if(relAbund > maxRelAbund){     maxRelAbund = relAbund; }
39                 }
40                 
41                 
42                 vector<string> scaleRelAbund(rabund->size(), "");
43                 
44                 for(int i=0;i<rabund->size();i++){
45                         float relAbund = rabund->get(i) / (float)rabund->getNumSeqs();
46                         
47                         if (rabund->get(i) != 0) { //don't want log value of 0.
48                                 if (scaler == "log10") {
49                                         scaleRelAbund[i] = toHex(int(255 * log10(relAbund) / log10(maxRelAbund))) + "0000";  
50                                 }else if (scaler == "log2") {
51                                         scaleRelAbund[i] = toHex(int(255 * log2(relAbund) / log2(maxRelAbund))) + "0000";  
52                                 }else if (scaler == "linear") {
53                                         scaleRelAbund[i] = toHex(int(255 * relAbund / maxRelAbund)) + "0000";  
54                                 }else {  //if user enters invalid scaler option.
55                                         scaleRelAbund[i] = toHex(int(255 * log10(relAbund / log10(maxRelAbund))))  + "0000"; 
56                                 } 
57                         }
58                         else { scaleRelAbund[i] = "FFFFFF";  }
59                 }
60                 
61                 
62                 string filenamesvg = outputDir + getRootName(getSimpleName(globaldata->inputFileName)) + rabund->getLabel() + ".heatmap.bin.svg";
63                 openOutputFile(filenamesvg, outsvg);
64                 
65                 //svg image
66                 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";
67                 outsvg << "<g>\n";
68                 
69                 //white backround
70                 outsvg << "<rect fill=\"white\" stroke=\"white\" x=\"0\" y=\"0\" width=\"" + toString(300) + "\" height=\"" + toString((rabund->getNumBins()*5 + 120))  + "\"/>"; 
71                 outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString((150) - 40) + "\" y=\"25\">Heatmap at distance " + rabund->getLabel() + "</text>\n";
72                                 
73                 //output legend and color labels
74                 string color;
75                 int x = 0;
76                 int y = 103 + (rabund->getNumBins()*5);
77                 printLegend(y, maxRelAbund);
78                 
79                 y = 70;
80                 for (int i = 0; i < scaleRelAbund.size(); i++) {
81                         
82                         outsvg << "<rect fill=\"#" + scaleRelAbund[i] + "\" stroke=\"#" + scaleRelAbund[i] + "\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"300\" height=\"5\"/>\n";
83                         y += 5;
84                 }
85                 
86                 outsvg << "</g>\n</svg>\n";
87                 outsvg.close();
88                 
89                 return filenamesvg;
90         }
91         catch(exception& e) {
92                 m->errorOut(e, "HeatMap", "getPic");
93                 exit(1);
94         }
95 }
96
97 //**********************************************************************************************************************
98
99 string HeatMap::getPic(vector<SharedRAbundVector*> lookup) {
100         try {
101                 //sort lookup so shared bins are on top
102                 if (isTrue(sorted) == true) {  sortSharedVectors(lookup);  }
103                 
104                 vector<vector<string> > scaleRelAbund;
105                 vector<float> maxRelAbund(lookup.size(), 0.0);          
106                 float superMaxRelAbund = 0;
107                 
108                 for(int i = 0; i < lookup.size(); i++){
109                         for(int j=0; j<lookup[i]->size(); j++){
110                                 
111                                 float relAbund = lookup[i]->getAbundance(j) / (float)lookup[i]->getNumSeqs();
112                                 if(relAbund > maxRelAbund[i]){  maxRelAbund[i] = relAbund;      }
113                         }
114                         if(maxRelAbund[i] > superMaxRelAbund){  superMaxRelAbund = maxRelAbund[i];      }
115                 }
116                 
117                 scaleRelAbund.resize(lookup.size());
118                 for(int i=0;i<lookup.size();i++){
119                         scaleRelAbund[i].assign(lookup[i]->size(), "");
120                         for(int j=0;j<lookup[i]->size();j++){
121                                 float relAbund = lookup[i]->getAbundance(j) / (float)lookup[i]->getNumSeqs();
122                                 
123                                 if (lookup[i]->getAbundance(j) != 0) { //don't want log value of 0.
124                                         if (scaler == "log10") {
125                                                 scaleRelAbund[i][j] = toHex(int(255 * log10(relAbund) / log10(maxRelAbund[i]))) + "0000";  
126                                         }else if (scaler == "log2") {
127                                                 scaleRelAbund[i][j] = toHex(int(255 * log2(relAbund) / log2(maxRelAbund[i]))) + "0000";  
128                                         }else if (scaler == "linear") {
129                                                 scaleRelAbund[i][j] = toHex(int(255 * relAbund / maxRelAbund[i])) + "0000";  
130                                         }else {  //if user enters invalid scaler option.
131                                                 scaleRelAbund[i][j] = toHex(int(255 * log10(relAbund / log10(maxRelAbund[i]))))  + "0000"; 
132                                         } 
133                                 }else { scaleRelAbund[i][j] = "FFFFFF";  }
134
135                         }
136                 }
137
138                 string filenamesvg = outputDir + getRootName(getSimpleName(globaldata->inputFileName)) + lookup[0]->getLabel() + ".heatmap.bin.svg";
139                 openOutputFile(filenamesvg, outsvg);
140                 
141                 //svg image
142                 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";
143                 outsvg << "<g>\n";
144                 
145                 //white backround
146                 outsvg << "<rect fill=\"white\" stroke=\"white\" x=\"0\" y=\"0\" width=\"" + toString(lookup.size() * 300) + "\" height=\"" + toString((lookup[0]->getNumBins()*5 + 120))  + "\"/>"; 
147                 outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString((lookup.size() * 150) - 40) + "\" y=\"25\">Heatmap at distance " + lookup[0]->getLabel() + "</text>\n";
148                 
149                 //column labels
150                 for (int h = 0; h < lookup.size(); h++) {
151                         outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString(((300 * (h+1)) - 150) - ((int)lookup[h]->getGroup().length() / 2)) + "\" y=\"50\">" + lookup[h]->getGroup() + "</text>\n"; 
152                 }
153                 
154                 //output legend and color labels
155                 string color;
156                 int x = 0;
157                 int y = 103 + (lookup[0]->getNumBins()*5);
158                 printLegend(y, superMaxRelAbund);
159                 
160                 y = 70;
161                 for (int i = 0; i < scaleRelAbund[0].size(); i++) {
162                         for (int j = 0; j < scaleRelAbund.size(); j++) {
163                                 
164                                 outsvg << "<rect fill=\"#" + scaleRelAbund[j][i] + "\" stroke=\"#" + scaleRelAbund[j][i] + "\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"300\" height=\"5\"/>\n";
165                                 x += 300;
166                         }
167                         x = 0;
168                         y += 5;
169                 }
170                 
171                 outsvg << "</g>\n</svg>\n";
172                 outsvg.close();
173                 
174                 return filenamesvg;
175
176         }
177         catch(exception& e) {
178                 m->errorOut(e, "HeatMap", "getPic");
179                 exit(1);
180         }
181 }
182
183 //**********************************************************************************************************************
184 void HeatMap::sortSharedVectors(vector<SharedRAbundVector*>& lookup){
185         try {
186                 //copy lookup and then clear it to refill with sorted.
187                 //loop though lookup and determine if they are shared
188                 //if they are then insert in the front
189                 //if not push to back
190                 
191                 vector<SharedRAbundVector*> looktemp;
192                 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.
193                 map<int, int>::iterator it;
194                 int count;
195                 
196                 //create and initialize looktemp as a copy of lookup
197                 for (int i = 0; i < lookup.size(); i++) { 
198                         SharedRAbundVector* temp = new SharedRAbundVector(lookup[i]->getNumBins());
199                         temp->setLabel(lookup[i]->getLabel());
200                         temp->setGroup(lookup[i]->getGroup());
201                         //copy lookup i's info
202                         for (int j = 0; j < lookup[i]->size(); j++) {
203                                 temp->set(j, lookup[i]->getAbundance(j), lookup[i]->getGroup());
204                         }
205                         looktemp.push_back(temp);
206                 }
207                 
208                 //clear out lookup to create sorted lookup -- Sarah look at - this is causing segmentation faults
209                 for (int j = 0; j < lookup.size(); j++) {
210 //                      delete lookup[j];
211                 }
212                 lookup.clear();  //doesn't this do the job?
213                 
214                 //create and initialize lookup to empty vectors
215                 for (int i = 0; i < looktemp.size(); i++) { 
216                         SharedRAbundVector* temp = new SharedRAbundVector();
217                         temp->setLabel(looktemp[i]->getLabel());
218                         temp->setGroup(looktemp[i]->getGroup());
219                         lookup.push_back(temp); 
220                         
221                         //initialize place map
222                         place[i] = 0;
223                 }
224                 
225                 
226                 //for each bin
227                 for (int i = 0; i < looktemp[0]->size(); i++) {
228                         count = 0;
229                         bool updatePlace = false;
230                         //for each group
231                         for (int j = 0; j < looktemp.size(); j++) {
232                                 if (looktemp[j]->getAbundance(i) != 0) { count++; }
233                         }
234                         
235                         //fill lookup
236                         for (int j = 0; j < looktemp.size(); j++) {
237                                 //if they are not shared then push to back, if they are not insert in front
238                                 if (count < 2)  { lookup[j]->push_back(looktemp[j]->getAbundance(i), looktemp[j]->getGroup()); }
239                                 //they are shared by some
240                                 else {  lookup[j]->insert(looktemp[j]->getAbundance(i), place[count], looktemp[j]->getGroup());   updatePlace = true; }
241                         }
242                         
243                         if (updatePlace == true) {
244                                 //move place holders below where you entered up to "make space" for you entry
245                                 for (it = place.begin(); it!= place.end(); it++) {  
246                                         if (it->first < count) { it->second++; }
247                                 }
248                         }
249                 }
250                 
251                 //delete looktemp -- Sarah look at - this is causing segmentation faults
252                 for (int j = 0; j < looktemp.size(); j++) {
253 //                      delete looktemp[j];
254                 }
255                 
256         }
257         catch(exception& e) {
258                 m->errorOut(e, "HeatMap", "sortSharedVectors");
259                 exit(1);
260         }
261 }
262
263 //**********************************************************************************************************************
264
265 void HeatMap::printLegend(int y, float maxbin) {
266         try {
267                 
268                 //output legend and color labels
269                 //go through map and give each score a color value
270                 string color;
271                 int x = 10;
272                 
273                 //prints legend
274                 for (int i = 1; i < 255; i++) {
275                         color = toHex(int((float)(i)));
276                         outsvg << "<rect fill=\"#" + color + "0000\" stroke=\"#" + color + "0000\" x=\"" + toString(x) + "\" y=\"" + toString(y) + "\" width=\"1\" height=\"10\"/>\n";
277                         x += 1;
278                 }
279                 
280                 //prints legend labels
281                 x = 10;
282                 for (int i = 1; i<=5; i++) {
283                         float label;
284                         if(scaler== "log10")            {       label = maxbin * log10(51*i) / log10(255);      }
285                         else if(scaler== "log2")        {       label = maxbin * log2(51*i) / log2(255);        }
286                         else if(scaler== "linear")      {       label = maxbin * 51 * i / 255;                          }
287                         else                                            {       label = maxbin * log10(51*i) / log10(255);      }
288                         label = int(label * 1000 + 0.5);
289                         label /= 1000.0;
290                         string text = toString(label, 3);
291                         
292                         outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString(x) + "\" y=\"" + toString(y-3) + "\">" + text + "</text>\n";
293                         x += 60;
294                 }
295         }
296         
297         catch(exception& e) {
298                 m->errorOut(e, "HeatMap", "printLegend");
299                 exit(1);
300         }
301 }
302
303
304
305