X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=preclustercommand.cpp;h=951b2008b062c26c5fabb54dfd8ef2d2a858da67;hb=957d67f7d8bbadfd2930de061e89fd9b149270fd;hp=0810a02d4351ff6b0285b7a28bf42e3a5bda4f71;hpb=192b4636345c51d962d4711206535e34cb2fd97c;p=mothur.git diff --git a/preclustercommand.cpp b/preclustercommand.cpp index 0810a02..951b200 100644 --- a/preclustercommand.cpp +++ b/preclustercommand.cpp @@ -51,7 +51,28 @@ string PreClusterCommand::getHelpString(){ exit(1); } } - +//********************************************************************************************************************** +string PreClusterCommand::getOutputFileNameTag(string type, string inputName=""){ + try { + string outputFileName = ""; + map >::iterator it; + + //is this a type this command creates + it = outputTypes.find(type); + if (it == outputTypes.end()) { m->mothurOut("[ERROR]: this command doesn't create a " + type + " output file.\n"); } + else { + if (type == "fasta") { outputFileName = "precluster" + m->getExtension(inputName); } + else if (type == "name") { outputFileName = "precluster.names"; } + else if (type == "map") { outputFileName = "precluster.map"; } + else { m->mothurOut("[ERROR]: No definition for type " + type + " output file tag.\n"); m->control_pressed = true; } + } + return outputFileName; + } + catch(exception& e) { + m->errorOut(e, "PreClusterCommand", "getOutputFileNameTag"); + exit(1); + } +} //********************************************************************************************************************** PreClusterCommand::PreClusterCommand(){ try { @@ -60,6 +81,7 @@ PreClusterCommand::PreClusterCommand(){ vector tempOutNames; outputTypes["fasta"] = tempOutNames; outputTypes["name"] = tempOutNames; + outputTypes["map"] = tempOutNames; } catch(exception& e) { m->errorOut(e, "PreClusterCommand", "PreClusterCommand"); @@ -94,6 +116,7 @@ PreClusterCommand::PreClusterCommand(string option) { vector tempOutNames; outputTypes["fasta"] = tempOutNames; outputTypes["name"] = tempOutNames; + outputTypes["map"] = tempOutNames; //if the user changes the input directory command factory will send this info to us in the output parameter string inputDir = validParameter.validFile(parameters, "inputdir", false); @@ -145,7 +168,7 @@ PreClusterCommand::PreClusterCommand(string option) { // ...at some point should added some additional type checking... namefile = validParameter.validFile(parameters, "name", true); if (namefile == "not found") { namefile = ""; } - else if (namefile == "not open") { abort = true; } + else if (namefile == "not open") { namefile = ""; abort = true; } else { m->setNameFile(namefile); } groupfile = validParameter.validFile(parameters, "group", true); @@ -154,13 +177,16 @@ PreClusterCommand::PreClusterCommand(string option) { else { m->setGroupFile(groupfile); bygroup = true; } string temp = validParameter.validFile(parameters, "diffs", false); if(temp == "not found"){ temp = "1"; } - convert(temp, diffs); + m->mothurConvert(temp, diffs); temp = validParameter.validFile(parameters, "processors", false); if (temp == "not found"){ temp = m->getProcessors(); } m->setProcessors(temp); - convert(temp, processors); - + m->mothurConvert(temp, processors); + if (namefile == "") { + vector files; files.push_back(fastafile); + parser.getNameFile(files); + } } } @@ -179,13 +205,18 @@ int PreClusterCommand::execute(){ int start = time(NULL); string fileroot = outputDir + m->getRootName(m->getSimpleName(fastafile)); - string newFastaFile = fileroot + "precluster" + m->getExtension(fastafile); - string newNamesFile = fileroot + "precluster.names"; + string newFastaFile = fileroot + getOutputFileNameTag("fasta", fastafile); + string newNamesFile = fileroot + getOutputFileNameTag("name"); + string newMapFile = fileroot + getOutputFileNameTag("map"); //add group name if by group + outputNames.push_back(newFastaFile); outputTypes["fasta"].push_back(newFastaFile); + outputNames.push_back(newNamesFile); outputTypes["name"].push_back(newNamesFile); + if (bygroup) { //clear out old files ofstream outFasta; m->openOutputFile(newFastaFile, outFasta); outFasta.close(); ofstream outNames; m->openOutputFile(newNamesFile, outNames); outNames.close(); + newMapFile = fileroot + "precluster."; //parse fasta and name file by group SequenceParser* parser; @@ -194,16 +225,12 @@ int PreClusterCommand::execute(){ vector groups = parser->getNamesOfGroups(); -//#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) - if(processors == 1) { driverGroups(parser, newFastaFile, newNamesFile, 0, groups.size(), groups); } - else { createProcessesGroups(parser, newFastaFile, newNamesFile, groups); } -//#else -// driverGroups(parser, newFastaFile, newNamesFile, 0, groups.size(), groups); -//#endif + if(processors == 1) { driverGroups(parser, newFastaFile, newNamesFile, newMapFile, 0, groups.size(), groups); } + else { createProcessesGroups(parser, newFastaFile, newNamesFile, newMapFile, groups); } delete parser; - if (m->control_pressed) { m->mothurRemove(newFastaFile); m->mothurRemove(newNamesFile); return 0; } + if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; } //run unique.seqs for deconvolute results string inputString = "fasta=" + newFastaFile; @@ -211,17 +238,19 @@ int PreClusterCommand::execute(){ m->mothurOutEndLine(); m->mothurOut("/******************************************/"); m->mothurOutEndLine(); m->mothurOut("Running command: unique.seqs(" + inputString + ")"); m->mothurOutEndLine(); - + m->mothurCalling = true; + Command* uniqueCommand = new DeconvoluteCommand(inputString); uniqueCommand->execute(); map > filenames = uniqueCommand->getOutputFiles(); delete uniqueCommand; - + m->mothurCalling = false; m->mothurOut("/******************************************/"); m->mothurOutEndLine(); m->renameFile(filenames["fasta"][0], newFastaFile); + m->renameFile(filenames["name"][0], newNamesFile); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to run pre.cluster."); m->mothurOutEndLine(); @@ -231,14 +260,15 @@ int PreClusterCommand::execute(){ //reads fasta file and return number of seqs int numSeqs = readFASTA(); //fills alignSeqs and makes all seqs active - if (m->control_pressed) { return 0; } + if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; } if (numSeqs == 0) { m->mothurOut("Error reading fasta file...please correct."); m->mothurOutEndLine(); return 0; } if (diffs > length) { m->mothurOut("Error: diffs is greater than your sequence length."); m->mothurOutEndLine(); return 0; } - int count = process(); + int count = process(newMapFile); + outputNames.push_back(newMapFile); outputTypes["map"].push_back(newMapFile); - if (m->control_pressed) { return 0; } + if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; } m->mothurOut("Total number of sequences before precluster was " + toString(alignSeqs.size()) + "."); m->mothurOutEndLine(); m->mothurOut("pre.cluster removed " + toString(count) + " sequences."); m->mothurOutEndLine(); m->mothurOutEndLine(); @@ -246,13 +276,12 @@ int PreClusterCommand::execute(){ m->mothurOut("It took " + toString(time(NULL) - start) + " secs to cluster " + toString(numSeqs) + " sequences."); m->mothurOutEndLine(); } - - if (m->control_pressed) { m->mothurRemove(newFastaFile); m->mothurRemove(newNamesFile); return 0; } + + if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; } m->mothurOutEndLine(); m->mothurOut("Output File Names: "); m->mothurOutEndLine(); - m->mothurOut(newFastaFile); m->mothurOutEndLine(); outputNames.push_back(newFastaFile); outputTypes["fasta"].push_back(newFastaFile); - m->mothurOut(newNamesFile); m->mothurOutEndLine(); outputNames.push_back(newNamesFile); outputTypes["name"].push_back(newNamesFile); + for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); } m->mothurOutEndLine(); //set fasta file as new current fastafile @@ -276,7 +305,7 @@ int PreClusterCommand::execute(){ } } /**************************************************************************************************/ -int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newFName, string newNName, vector groups) { +int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newFName, string newNName, string newMFile, vector groups) { try { vector processIDS; @@ -296,7 +325,7 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF lines.push_back(linePair(startIndex, endIndex)); } -#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) +#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix) //loop through and create all the processes you want while (process != processors) { @@ -306,7 +335,17 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF processIDS.push_back(pid); //create map from line number to pid so you can append files in correct order later process++; }else if (pid == 0){ - num = driverGroups(parser, newFName + toString(getpid()) + ".temp", newNName + toString(getpid()) + ".temp", lines[process].start, lines[process].end, groups); + outputNames.clear(); + num = driverGroups(parser, newFName + toString(getpid()) + ".temp", newNName + toString(getpid()) + ".temp", newMFile, lines[process].start, lines[process].end, groups); + + string tempFile = toString(getpid()) + ".outputNames.temp"; + ofstream outTemp; + m->openOutputFile(tempFile, outTemp); + + outTemp << outputNames.size(); + for (int i = 0; i < outputNames.size(); i++) { outTemp << outputNames[i] << endl; } + outTemp.close(); + exit(0); }else { m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); @@ -316,14 +355,30 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF } //do my part - num = driverGroups(parser, newFName, newNName, lines[0].start, lines[0].end, groups); + num = driverGroups(parser, newFName, newNName, newMFile, lines[0].start, lines[0].end, groups); //force parent to wait until all the processes are done for (int i=0;iopenInputFile(tempFile, intemp); + + int num; + intemp >> num; + for (int k = 0; k < num; k++) { + string name = ""; + intemp >> name; m->gobble(intemp); + + outputNames.push_back(name); outputTypes["map"].push_back(name); + } + intemp.close(); + m->mothurRemove(tempFile); + } #else ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -340,7 +395,7 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF // Allocate memory for thread data. string extension = toString(i) + ".temp"; - preClusterData* tempPreCluster = new preClusterData(fastafile, namefile, groupfile, (newFName+extension), (newNName+extension), groups, m, lines[i].start, lines[i].end, diffs, i); + preClusterData* tempPreCluster = new preClusterData(fastafile, namefile, groupfile, (newFName+extension), (newNName+extension), newMFile, groups, m, lines[i].start, lines[i].end, diffs, i); pDataArray.push_back(tempPreCluster); processIDS.push_back(i); @@ -351,13 +406,16 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF //using the main process as a worker saves time and memory - num = driverGroups(parser, newFName, newNName, lines[0].start, lines[0].end, groups); + num = driverGroups(parser, newFName, newNName, newMFile, lines[0].start, lines[0].end, groups); //Wait until all threads have terminated. WaitForMultipleObjects(processors-1, hThreadArray, TRUE, INFINITE); //Close all thread handles and free memory allocations. for(int i=0; i < pDataArray.size(); i++){ + for (int j = 0; j < pDataArray[i]->mapFileNames.size(); j++) { + outputNames.push_back(pDataArray[i]->mapFileNames[j]); outputTypes["map"].push_back(pDataArray[i]->mapFileNames[j]); + } CloseHandle(hThreadArray[i]); delete pDataArray[i]; } @@ -366,6 +424,9 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF //append output files for(int i=0;igetFullPathName(".\\" + newFName); + //newNName = m->getFullPathName(".\\" + newNName); + m->appendFiles((newFName + toString(processIDS[i]) + ".temp"), newFName); m->mothurRemove((newFName + toString(processIDS[i]) + ".temp")); @@ -382,7 +443,7 @@ int PreClusterCommand::createProcessesGroups(SequenceParser* parser, string newF } } /**************************************************************************************************/ -int PreClusterCommand::driverGroups(SequenceParser* parser, string newFFile, string newNFile, int start, int end, vector groups){ +int PreClusterCommand::driverGroups(SequenceParser* parser, string newFFile, string newNFile, string newMFile, int start, int end, vector groups){ try { int numSeqs = 0; @@ -407,7 +468,8 @@ int PreClusterCommand::driverGroups(SequenceParser* parser, string newFFile, str if (diffs > length) { m->mothurOut("Error: diffs is greater than your sequence length."); m->mothurOutEndLine(); m->control_pressed = true; return 0; } - int count = process(); + int count = process(newMFile+groups[i]+".map"); + outputNames.push_back(newMFile+groups[i]+".map"); outputTypes["map"].push_back(newMFile+groups[i]+".map"); if (m->control_pressed) { return 0; } @@ -427,8 +489,10 @@ int PreClusterCommand::driverGroups(SequenceParser* parser, string newFFile, str } } /**************************************************************************************************/ -int PreClusterCommand::process(){ +int PreClusterCommand::process(string newMapFile){ try { + ofstream out; + m->openOutputFile(newMapFile, out); //sort seqs by number of identical seqs sort(alignSeqs.begin(), alignSeqs.end(), comparePriority); @@ -444,10 +508,12 @@ int PreClusterCommand::process(){ if (alignSeqs[i].active) { //this sequence has not been merged yet + string chunk = alignSeqs[i].seq.getName() + "\t" + toString(alignSeqs[i].numIdentical) + "\t" + toString(0) + "\t" + alignSeqs[i].seq.getAligned() + "\n"; + //try to merge it with all smaller seqs for (int j = i+1; j < numSeqs; j++) { - if (m->control_pressed) { return 0; } + if (m->control_pressed) { out.close(); return 0; } if (alignSeqs[j].active) { //this sequence has not been merged yet //are you within "diff" bases @@ -458,19 +524,24 @@ int PreClusterCommand::process(){ alignSeqs[i].names += ',' + alignSeqs[j].names; alignSeqs[i].numIdentical += alignSeqs[j].numIdentical; + chunk += alignSeqs[j].seq.getName() + "\t" + toString(alignSeqs[j].numIdentical) + "\t" + toString(mismatch) + "\t" + alignSeqs[j].seq.getAligned() + "\n"; + alignSeqs[j].active = 0; alignSeqs[j].numIdentical = 0; count++; } }//end if j active - }//end if i != j + }//end for loop j //remove from active list alignSeqs[i].active = 0; + out << "ideal_seq_" << (i+1) << '\t' << alignSeqs[i].numIdentical << endl << chunk << endl;; + }//end if active i if(i % 100 == 0) { m->mothurOut(toString(i) + "\t" + toString(numSeqs - count) + "\t" + toString(count)); m->mothurOutEndLine(); } } + out.close(); if(numSeqs % 100 != 0) { m->mothurOut(toString(numSeqs) + "\t" + toString(numSeqs - count) + "\t" + toString(count)); m->mothurOutEndLine(); } @@ -492,7 +563,7 @@ int PreClusterCommand::readFASTA(){ m->openInputFile(fastafile, inFasta); //string firstCol, secondCol, nameString; - length = 0; + set lengths; while (!inFasta.eof()) { @@ -518,17 +589,21 @@ int PreClusterCommand::readFASTA(){ else{ seqPNode tempNode(itSize->second, seq, names[seq.getName()]); alignSeqs.push_back(tempNode); - if (seq.getAligned().length() > length) { length = seq.getAligned().length(); } + lengths.insert(seq.getAligned().length()); } }else { //no names file, you are identical to yourself seqPNode tempNode(1, seq, seq.getName()); alignSeqs.push_back(tempNode); - if (seq.getAligned().length() > length) { length = seq.getAligned().length(); } + lengths.insert(seq.getAligned().length()); } } } inFasta.close(); //inNames.close(); + + if (lengths.size() > 1) { m->control_pressed = true; m->mothurOut("[ERROR]: your sequences are not all the same length. pre.cluster requires sequences to be aligned."); m->mothurOutEndLine(); } + else if (lengths.size() == 1) { length = *(lengths.begin()); } + return alignSeqs.size(); } @@ -540,7 +615,7 @@ int PreClusterCommand::readFASTA(){ /**************************************************************************************************/ int PreClusterCommand::loadSeqs(map& thisName, vector& thisSeqs){ try { - length = 0; + set lengths; alignSeqs.clear(); map::iterator it; bool error = false; @@ -563,15 +638,18 @@ int PreClusterCommand::loadSeqs(map& thisName, vector& seqPNode tempNode(numReps, thisSeqs[i], it->second); alignSeqs.push_back(tempNode); - if (thisSeqs[i].getAligned().length() > length) { length = thisSeqs[i].getAligned().length(); } + lengths.insert(thisSeqs[i].getAligned().length()); } }else { //no names file, you are identical to yourself seqPNode tempNode(1, thisSeqs[i], thisSeqs[i].getName()); alignSeqs.push_back(tempNode); - if (thisSeqs[i].getAligned().length() > length) { length = thisSeqs[i].getAligned().length(); } + lengths.insert(thisSeqs[i].getAligned().length()); } } + if (lengths.size() > 1) { error = true; m->mothurOut("[ERROR]: your sequences are not all the same length. pre.cluster requires sequences to be aligned."); m->mothurOutEndLine(); } + else if (lengths.size() == 1) { length = *(lengths.begin()); } + //sanity check if (error) { m->control_pressed = true; } @@ -620,7 +698,7 @@ void PreClusterCommand::printData(string newfasta, string newname){ m->openOutputFile(newfasta, outFasta); m->openOutputFile(newname, outNames); } - + for (int i = 0; i < alignSeqs.size(); i++) { if (alignSeqs[i].numIdentical != 0) { alignSeqs[i].seq.printSequence(outFasta);