5 * Created by westcott on 9/8/09.
6 * Copyright 2009 Schloss Lab. All rights reserved.
10 #include "chimeracheckrdp.h"
12 //***************************************************************************************************************
13 ChimeraCheckRDP::ChimeraCheckRDP(string filename, string temp, string n, bool s, int inc, int k, string o) : Chimera() {
16 templateFileName = temp;
23 templateDB = new AlignmentDB(templateFileName, "kmer", kmerSize, 0.0,0.0,0.0,0.0);
24 m->mothurOutEndLine();
26 kmer = new Kmer(kmerSize);
29 readName(name); //fills name map with names of seqs the user wants to have .svg for.
33 m->errorOut(e, "ChimeraCheckRDP", "ChimeraCheckRDP");
37 //***************************************************************************************************************
39 ChimeraCheckRDP::~ChimeraCheckRDP() {
45 m->errorOut(e, "ChimeraCheckRDP", "~ChimeraCheckRDP");
49 //***************************************************************************************************************
50 Sequence* ChimeraCheckRDP::print(ostream& out, ostream& outAcc) {
53 m->mothurOut("Processing: " + querySeq->getName()); m->mothurOutEndLine();
55 out << querySeq->getName() << endl;
56 out << "IS scores: " << '\t';
58 for (int k = 0; k < IS.size(); k++) {
59 out << IS[k].score << '\t';
64 if (name != "") { //if user has specific names
65 map<string, string>::iterator it = names.find(querySeq->getName());
67 if (it != names.end()) { //user wants pic of this
68 makeSVGpic(IS); //zeros out negative results
70 }else{//output them all
71 makeSVGpic(IS); //zeros out negative results
78 m->errorOut(e, "ChimeraCheckRDP", "print");
83 //***************************************************************************************************************
84 Sequence* ChimeraCheckRDP::print(MPI_File& out, MPI_File& outAcc) {
87 cout << "Processing: " << querySeq->getName() << endl;
89 string outString = "";
91 outString += querySeq->getName() + "\nIS scores: \t";
93 for (int k = 0; k < IS.size(); k++) {
94 outString += toString(IS[k].score) + "\t";
99 int length = outString.length();
100 char* buf = new char[length];
101 memcpy(buf, outString.c_str(), length);
103 MPI_File_write_shared(out, buf, length, MPI_CHAR, &status);
107 if (name != "") { //if user has specific names
108 map<string, string>::iterator it = names.find(querySeq->getName());
110 if (it != names.end()) { //user wants pic of this
111 makeSVGpic(IS); //zeros out negative results
113 }else{//output them all
114 makeSVGpic(IS); //zeros out negative results
120 catch(exception& e) {
121 m->errorOut(e, "ChimeraCheckRDP", "print");
126 //***************************************************************************************************************
127 int ChimeraCheckRDP::getChimeras(Sequence* query) {
134 closest = templateDB->findClosestSequence(query);
138 //determine chimera report cutoff - window score above 95%
139 //getCutoff(); - not very acurate predictor
143 catch(exception& e) {
144 m->errorOut(e, "ChimeraCheckRDP", "getChimeras");
148 //***************************************************************************************************************
149 vector<sim> ChimeraCheckRDP::findIS() {
153 vector< map<int, int> > queryKmerInfo; //vector of maps - each entry in the vector is a map of the kmers up to that spot in the unaligned seq
154 //example: seqKmerInfo[50] = map containing the kmers found in the first 50 + kmersize characters of ecoli.
155 //i chose to store the kmers numbers in a map so you wouldn't have to check for dupilcate entries and could easily find the
156 //kmers 2 seqs had in common. There may be a better way to do this thats why I am leaving so many comments...
157 vector< map<int, int> > subjectKmerInfo;
159 vector<sim> isValues;
160 string queryName = querySeq->getName();
161 string seq = querySeq->getUnaligned();
163 queryKmerInfo = kmer->getKmerCounts(seq);
164 subjectKmerInfo = kmer->getKmerCounts(closest.getUnaligned());
166 //find total kmers you have in common with closest[query] by looking at the last entry in the vector of maps for each
167 int nTotal = calcKmers(queryKmerInfo[(queryKmerInfo.size()-1)], subjectKmerInfo[(subjectKmerInfo.size()-1)]);
169 //you don't want the starting point to be virtually at hte end so move it in 10%
170 int start = seq.length() / 10;
173 for (int f = start; f < (seq.length() - start); f+=increment) {
175 if (m->control_pressed) { return isValues; }
177 if ((f - kmerSize) < 0) { m->mothurOut("Your sequence is too short for your kmerSize."); m->mothurOutEndLine(); exit(1); }
181 string fragLeft = seq.substr(0, f); //left side of breakpoint
182 string fragRight = seq.substr(f); //right side of breakpoint
184 //make a sequence of the left side and right side
185 Sequence* left = new Sequence(queryName, fragLeft);
186 Sequence* right = new Sequence(queryName, fragRight);
188 //find seqs closest to each fragment
189 Sequence closestLeft = templateDB->findClosestSequence(left);
191 Sequence closestRight = templateDB->findClosestSequence(right);
193 //get kmerinfo for the closest left
194 vector< map<int, int> > closeLeftKmerInfo = kmer->getKmerCounts(closestLeft.getUnaligned());
196 //get kmerinfo for the closest right
197 vector< map<int, int> > closeRightKmerInfo = kmer->getKmerCounts(closestRight.getUnaligned());
199 //right side is tricky - since the counts grow on eachother to find the correct counts of only the right side you must subtract the counts of the left side
200 //iterate through left sides map to subtract the number of times you saw things before you got the the right side
201 map<int, int> rightside = queryKmerInfo[queryKmerInfo.size()-1];
202 for (map<int, int>::iterator itleft = queryKmerInfo[f-kmerSize].begin(); itleft != queryKmerInfo[f-kmerSize].end(); itleft++) {
203 int howManyTotal = queryKmerInfo[queryKmerInfo.size()-1][itleft->first]; //times that kmer was seen in total
205 //itleft->second is times it was seen in left side, so howmanytotal - leftside should give you right side
206 int howmanyright = howManyTotal - itleft->second;
208 //if any were seen just on the left erase
209 if (howmanyright == 0) {
210 rightside.erase(itleft->first);
214 map<int, int> closerightside = closeRightKmerInfo[closeRightKmerInfo.size()-1];
215 for (map<int, int>::iterator itright = closeRightKmerInfo[f-kmerSize].begin(); itright != closeRightKmerInfo[f-kmerSize].end(); itright++) {
216 int howManyTotal = closeRightKmerInfo[(closeRightKmerInfo.size()-1)][itright->first]; //times that kmer was seen in total
218 //itleft->second is times it was seen in left side, so howmanytotal - leftside should give you right side
219 int howmanyright = howManyTotal - itright->second;
221 //if any were seen just on the left erase
222 if (howmanyright == 0) {
223 closerightside.erase(itright->first);
228 int nLeft = calcKmers(closeLeftKmerInfo[f-kmerSize], queryKmerInfo[f-kmerSize]);
230 int nRight = calcKmers(closerightside, rightside);
232 int is = nLeft + nRight - nTotal;
234 //save IS, leftparent, rightparent, breakpoint
235 temp.leftParent = closestLeft.getName();
236 temp.rightParent = closestRight.getName();
240 isValues.push_back(temp);
249 catch(exception& e) {
250 m->errorOut(e, "ChimeraCheckRDP", "findIS");
254 //***************************************************************************************************************
255 void ChimeraCheckRDP::readName(string namefile) {
266 //char* inFileName = new char[namefile.length()];
267 //memcpy(inFileName, namefile.c_str(), namefile.length());
269 char inFileName[1024];
270 strcpy(inFileName, namefile.c_str());
272 MPI_File_open(MPI_COMM_WORLD, inFileName, MPI_MODE_RDONLY, MPI_INFO_NULL, &inMPI);
273 MPI_File_get_size(inMPI, &size);
277 char* buffer = new char[size];
278 MPI_File_read(inMPI, buffer, size, MPI_CHAR, &status);
280 string tempBuf = buffer;
281 if (tempBuf.length() > size) { tempBuf = tempBuf.substr(0, size); }
282 istringstream iss (tempBuf,istringstream::in);
286 iss >> name; m->gobble(iss);
290 MPI_File_close(&inMPI);
295 m->openInputFile(namefile, in);
298 in >> name; m->gobble(in);
306 catch(exception& e) {
307 m->errorOut(e, "ChimeraCheckRDP", "readName");
312 //***************************************************************************************************************
313 //find the smaller map and iterate through it and count kmers in common
314 int ChimeraCheckRDP::calcKmers(map<int, int> query, map<int, int> subject) {
319 map<int, int>::iterator smallone;
320 map<int, int>::iterator largeone;
322 if (query.size() < subject.size()) {
324 for (smallone = query.begin(); smallone != query.end(); smallone++) {
325 largeone = subject.find(smallone->first);
327 //if you found it they have that kmer in common
328 if (largeone != subject.end()) { common++; }
333 for (smallone = subject.begin(); smallone != subject.end(); smallone++) {
334 largeone = query.find(smallone->first);
336 //if you found it they have that kmer in common
337 if (largeone != query.end()) { common++; }
344 catch(exception& e) {
345 m->errorOut(e, "ChimeraCheckRDP", "calcKmers");
350 //***************************************************************************************************************
351 void ChimeraCheckRDP::makeSVGpic(vector<sim> info) {
354 string file = outputDir + querySeq->getName() + ".chimeracheck.svg";
357 int outMode=MPI_MODE_CREATE|MPI_MODE_WRONLY;
359 //char* FileName = new char[file.length()];
360 //memcpy(FileName, file.c_str(), file.length());
363 strcpy(FileName, file.c_str());
365 MPI_File_open(MPI_COMM_SELF, FileName, outMode, MPI_INFO_NULL, &outSVG); //comm, filename, mode, info, filepointer
369 int width = (info.size()*5) + 150;
371 string outString = "";
373 outString += "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 700 " + toString(width) + "\">\n";
374 outString += "<g>\n";
375 outString += "<text fill=\"black\" class=\"seri\" x=\"" + toString((width / 2) - 150) + "\" y=\"25\">Plotted IS values for " + querySeq->getName() + "</text>\n";
377 outString += "<line x1=\"75\" y1=\"600\" x2=\"" + toString((info.size()*5) + 75) + "\" y2=\"600\" stroke=\"black\" stroke-width=\"2\"/>\n";
378 outString += "<line x1=\"75\" y1=\"600\" x2=\"75\" y2=\"125\" stroke=\"black\" stroke-width=\"2\"/>\n";
380 outString += "<text fill=\"black\" class=\"seri\" x=\"80\" y=\"620\">" + toString(info[0].midpoint) + "</text>\n";
381 outString += "<text fill=\"black\" class=\"seri\" x=\"" + toString((info.size()*5) + 75) + "\" y=\"620\">" + toString(info[info.size()-1].midpoint) + "</text>\n";
382 outString += "<text fill=\"black\" class=\"seri\" x=\"" + toString((width / 2) - 150) + "\" y=\"650\">Base Positions</text>\n";
384 outString += "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"580\">0</text>\n";
386 outString += "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"350\">IS</text>\n";
391 for (int i = 0; i < info.size(); i++) {
392 if (info[i].score > biggest) {
393 biggest = info[i].score;
397 outString += "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"135\">" + toString(biggest) + "</text>\n";
399 int scaler2 = 500 / biggest;
402 outString += "<polyline fill=\"none\" stroke=\"red\" stroke-width=\"2\" points=\"";
403 //160,200 180,230 200,210 234,220\"/> ";
404 for (int i = 0; i < info.size(); i++) {
405 if(info[i].score < 0) { info[i].score = 0; }
406 outString += toString(((i*5) + 75)) + "," + toString((600 - (info[i].score * scaler2))) + " ";
409 outString += "\"/> ";
410 outString += "</g>\n</svg>\n";
413 int length = outString.length();
414 char* buf2 = new char[length];
415 memcpy(buf2, outString.c_str(), length);
417 MPI_File_write(outSVG, buf2, length, MPI_CHAR, &status);
420 MPI_File_close(&outSVG);
423 catch(exception& e) {
424 m->errorOut(e, "ChimeraCheckRDP", "makeSVGpic");
429 //***************************************************************************************************************
430 void ChimeraCheckRDP::makeSVGpic(vector<sim> info) {
433 string file = outputDir + querySeq->getName() + ".chimeracheck.svg";
435 m->openOutputFile(file, outsvg);
437 int width = (info.size()*5) + 150;
439 outsvg << "<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\" viewBox=\"0 0 700 " + toString(width) + "\">\n";
441 outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString((width / 2) - 150) + "\" y=\"25\">Plotted IS values for " + querySeq->getName() + "</text>\n";
443 outsvg << "<line x1=\"75\" y1=\"600\" x2=\"" + toString((info.size()*5) + 75) + "\" y2=\"600\" stroke=\"black\" stroke-width=\"2\"/>\n";
444 outsvg << "<line x1=\"75\" y1=\"600\" x2=\"75\" y2=\"125\" stroke=\"black\" stroke-width=\"2\"/>\n";
446 outsvg << "<text fill=\"black\" class=\"seri\" x=\"80\" y=\"620\">" + toString(info[0].midpoint) + "</text>\n";
447 outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString((info.size()*5) + 75) + "\" y=\"620\">" + toString(info[info.size()-1].midpoint) + "</text>\n";
448 outsvg << "<text fill=\"black\" class=\"seri\" x=\"" + toString((width / 2) - 150) + "\" y=\"650\">Base Positions</text>\n";
450 outsvg << "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"580\">0</text>\n";
452 outsvg << "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"350\">IS</text>\n";
457 for (int i = 0; i < info.size(); i++) {
458 if (info[i].score > biggest) {
459 biggest = info[i].score;
463 outsvg << "<text fill=\"black\" class=\"seri\" x=\"50\" y=\"135\">" + toString(biggest) + "</text>\n";
465 int scaler2 = 500 / biggest;
468 outsvg << "<polyline fill=\"none\" stroke=\"red\" stroke-width=\"2\" points=\"";
469 //160,200 180,230 200,210 234,220\"/> ";
470 for (int i = 0; i < info.size(); i++) {
471 if(info[i].score < 0) { info[i].score = 0; }
472 outsvg << ((i*5) + 75) << "," << (600 - (info[i].score * scaler2)) << " ";
476 outsvg << "</g>\n</svg>\n";
481 catch(exception& e) {
482 m->errorOut(e, "ChimeraCheckRDP", "makeSVGpic");
487 //***************************************************************************************************************/