2 // mergesfffilecommand.cpp
5 // Created by Sarah Westcott on 1/31/14.
6 // Copyright (c) 2014 Schloss Lab. All rights reserved.
9 #include "mergesfffilecommand.h"
10 #include "endiannessmacros.h"
12 //**********************************************************************************************************************
13 vector<string> MergeSfffilesCommand::setParameters(){
15 CommandParameter psff("sff", "InputTypes", "", "", "sffFile", "sffFile", "none","sff",false,false); parameters.push_back(psff);
16 CommandParameter pfile("file", "InputTypes", "", "", "sffFile", "sffFile", "none","sff",false,false); parameters.push_back(pfile);
17 CommandParameter poutput("output", "String", "", "", "", "", "","",false,true,true); parameters.push_back(poutput);
18 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
19 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
21 vector<string> myArray;
22 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
26 m->errorOut(e, "MergeSfffilesCommand", "setParameters");
30 //**********************************************************************************************************************
31 string MergeSfffilesCommand::getHelpString(){
33 string helpString = "";
34 helpString += "The merge.sfffiles command reads a sff file or a file containing a list of sff files and merges the individual files into a single sff file. \n";
35 helpString += "The merge.sfffiles command parameters are sff, file and output. sff or file is required. \n";
36 helpString += "The sff parameter allows you to enter the sff list of sff files separated by -'s.\n";
37 helpString += "The file parameter allows you to provide a file containing a list of sff files to merge. \n";
38 helpString += "The output parameter allows you to provide an output filename. \n";
39 helpString += "Example sffinfo(sff=mySffFile.sff-mySecond.sff).\n";
40 helpString += "Note: No spaces between parameter labels (i.e. sff), '=' and parameters (i.e.yourSffFileName).\n";
44 m->errorOut(e, "MergeSfffilesCommand", "getHelpString");
49 //**********************************************************************************************************************
50 string MergeSfffilesCommand::getOutputPattern(string type) {
54 if (type == "sff") { pattern = "[filename],"; }
55 else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true; }
60 m->errorOut(e, "MergeSfffilesCommand", "getOutputPattern");
64 //**********************************************************************************************************************
65 MergeSfffilesCommand::MergeSfffilesCommand(){
67 abort = true; calledHelp = true;
69 vector<string> tempOutNames;
70 outputTypes["sff"] = tempOutNames;
73 m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
77 //**********************************************************************************************************************
79 MergeSfffilesCommand::MergeSfffilesCommand(string option) {
81 abort = false; calledHelp = false;
83 //allow user to run help
84 if(option == "help") { help(); abort = true; calledHelp = true; }
85 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
88 //valid paramters for this command
89 vector<string> myArray = setParameters();
91 OptionParser parser(option);
92 map<string, string> parameters = parser.getParameters();
93 map<string,string>::iterator it;
95 ValidParameters validParameter;
96 //check to make sure all parameters are valid for command
97 for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) {
98 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
101 //initialize outputTypes
102 vector<string> tempOutNames;
103 outputTypes["sff"] = tempOutNames;
105 //if the user changes the output directory command factory will send this info to us in the output parameter
106 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){ outputDir = ""; }
108 //if the user changes the input directory command factory will send this info to us in the output parameter
109 string inputDir = validParameter.validFile(parameters, "inputdir", false); if (inputDir == "not found"){ inputDir = ""; }
111 it = parameters.find("file");
112 //user has given a template file
113 if(it != parameters.end()){
114 string path = m->hasPath(it->second);
115 //if the user has not given a path then, add inputdir. else leave path alone.
116 if (path == "") { parameters["file"] = inputDir + it->second; }
120 sffFilename = validParameter.validFile(parameters, "sff", false);
121 if (sffFilename == "not found") { sffFilename = ""; }
123 m->splitAtDash(sffFilename, filenames);
125 //go through files and make sure they are good, if not, then disregard them
126 for (int i = 0; i < filenames.size(); i++) {
128 if (filenames[i] == "current") {
129 filenames[i] = m->getSFFFile();
130 if (filenames[i] != "") { m->mothurOut("Using " + filenames[i] + " as input file for the sff parameter where you had given current."); m->mothurOutEndLine(); }
132 m->mothurOut("You have no current sfffile, ignoring current."); m->mothurOutEndLine(); ignore=true;
133 //erase from file list
134 filenames.erase(filenames.begin()+i);
140 if (inputDir != "") {
141 string path = m->hasPath(filenames[i]);
142 //if the user has not given a path then, add inputdir. else leave path alone.
143 if (path == "") { filenames[i] = inputDir + filenames[i]; }
147 int ableToOpen = m->openInputFile(filenames[i], in, "noerror");
149 //if you can't open it, try default location
150 if (ableToOpen == 1) {
151 if (m->getDefaultPath() != "") { //default path is set
152 string tryPath = m->getDefaultPath() + m->getSimpleName(filenames[i]);
153 m->mothurOut("Unable to open " + filenames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
155 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
157 filenames[i] = tryPath;
161 //if you can't open it, try default location
162 if (ableToOpen == 1) {
163 if (m->getOutputDir() != "") { //default path is set
164 string tryPath = m->getOutputDir() + m->getSimpleName(filenames[i]);
165 m->mothurOut("Unable to open " + filenames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
167 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
169 filenames[i] = tryPath;
175 if (ableToOpen == 1) {
176 m->mothurOut("Unable to open " + filenames[i] + ". It will be disregarded."); m->mothurOutEndLine();
177 //erase from file list
178 filenames.erase(filenames.begin()+i);
180 }else { m->setSFFFile(filenames[i]); }
185 file = validParameter.validFile(parameters, "file", true);
186 if (file == "not open") { abort = true; }
187 else if (file == "not found") { file = ""; }
189 if ((file == "") && (filenames.size() == 0)) {
190 m->mothurOut("[ERROR]: no valid files."); m->mothurOutEndLine(); abort = true;
193 if ((file != "") && (filenames.size() != 0)) { //both are given
194 m->mothurOut("[ERROR]: cannot use file option and sff option at the same time, choose one."); m->mothurOutEndLine(); abort = true;
197 outputFile = validParameter.validFile(parameters, "output", false);
198 if (outputFile == "not found") { m->mothurOut("you must enter an output file name"); m->mothurOutEndLine(); abort=true; }
199 if (outputDir != "") { outputFile = outputDir + m->getSimpleName(outputFile); }
203 catch(exception& e) {
204 m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
208 //**********************************************************************************************************************
209 int MergeSfffilesCommand::execute(){
211 if (abort == true) { if (calledHelp) { return 0; } return 2; }
215 if (outputDir == "") { outputDir = m->hasPath(file); }
218 map<string, string> variables;
219 string thisOutputDir = outputDir;
220 if (outputDir == "") { thisOutputDir += m->hasPath(outputFile); }
221 variables["[filename]"] = thisOutputDir + m->getSimpleName(outputFile);
222 outputFile = getOutputFileName("sff",variables);
223 m->openOutputFileBinary(outputFile, out);
224 outputNames.push_back(outputFile); outputTypes["sff"].push_back(outputFile);
225 outputFileHeader = outputFile + ".headers";
228 for (int s = 0; s < filenames.size(); s++) {
230 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
232 int start = time(NULL);
234 filenames[s] = m->getFullPathName(filenames[s]);
235 m->mothurOut("\nMerging info from " + filenames[s] + " ..." ); m->mothurOutEndLine();
237 int numReads = mergeSffInfo(filenames[s], out);
239 m->mothurOut("It took " + toString(time(NULL) - start) + " secs to merge " + toString(numReads) + ".\n");
243 //create new common header and add to merged file
244 adjustCommonHeader();
246 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
248 //set sff file as new current sff file
250 itTypes = outputTypes.find("sff");
251 if (itTypes != outputTypes.end()) {
252 if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSFFFile(current); }
255 //report output filenames
256 m->mothurOutEndLine();
257 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
258 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
259 m->mothurOutEndLine();
263 catch(exception& e) {
264 m->errorOut(e, "MergeSfffilesCommand", "execute");
268 //**********************************************************************************************************************
269 int MergeSfffilesCommand::mergeSffInfo(string input, ofstream& out){
271 currentFileName = input;
274 m->openInputFileBinary(input, in);
277 readCommonHeader(in, header);
281 //check magic number and version
282 if (header.magicNumber != 779314790) { m->mothurOut("Magic Number is not correct, not a valid .sff file"); m->mothurOutEndLine(); return count; }
283 if (header.version != "0001") { m->mothurOut("Version is not supported, only support version 0001."); m->mothurOutEndLine(); return count; }
285 //save for adjustHeader sanity check
286 commonHeaders.push_back(header);
288 //read through the sff file
292 seqRead read; Header readheader;
293 readSeqData(in, read, header.numFlowsPerRead, readheader, out);
295 bool okay = sanityCheck(readheader, read);
296 if (!okay) { break; }
301 if((count+1) % 10000 == 0){ m->mothurOut(toString(count+1)); m->mothurOutEndLine(); }
303 if (m->control_pressed) { count = 0; break; }
305 if (count >= header.numReads) { break; }
309 if (!m->control_pressed) { if((count) % 10000 != 0){ m->mothurOut(toString(count)); m->mothurOutEndLine(); } }
315 catch(exception& e) {
316 m->errorOut(e, "MergeSfffilesCommand", "mergeSffInfo");
320 //**********************************************************************************************************************
321 int MergeSfffilesCommand::readCommonHeader(ifstream& in, CommonHeader& header){
329 header.magicNumber = be_int4(*(unsigned int *)(&buffer));
335 for (int i = 0; i < 4; i++) { header.version += toString((int)(buffer9[i])); }
340 header.indexOffset = be_int8(*(unsigned long long *)(&buffer2));
345 header.indexLength = be_int4(*(unsigned int *)(&buffer3));
350 header.numReads = be_int4(*(unsigned int *)(&buffer4));
352 if (m->debug) { m->mothurOut("[DEBUG]: numReads = " + toString(header.numReads) + "\n"); }
357 header.headerLength = be_int2(*(unsigned short *)(&buffer5));
362 header.keyLength = be_int2(*(unsigned short *)(&buffer6));
364 //read number of flow reads
367 header.numFlowsPerRead = be_int2(*(unsigned short *)(&buffer7));
372 header.flogramFormatCode = (int)(buffer8[0]);
375 char* tempBuffer = new char[header.numFlowsPerRead];
376 in.read(&(*tempBuffer), header.numFlowsPerRead);
377 header.flowChars = tempBuffer;
378 if (header.flowChars.length() > header.numFlowsPerRead) { header.flowChars = header.flowChars.substr(0, header.numFlowsPerRead); }
382 char* tempBuffer2 = new char[header.keyLength];
383 in.read(&(*tempBuffer2), header.keyLength);
384 header.keySequence = tempBuffer2;
385 if (header.keySequence.length() > header.keyLength) { header.keySequence = header.keySequence.substr(0, header.keyLength); }
386 delete[] tempBuffer2;
389 unsigned long long spotInFile = in.tellg();
390 unsigned long long spot = (spotInFile + 7)& ~7; // ~ inverts
394 m->mothurOut("Error reading sff common header."); m->mothurOutEndLine();
400 catch(exception& e) {
401 m->errorOut(e, "MergeSfffilesCommand", "readCommonHeader");
405 //**********************************************************************************************************************
406 int MergeSfffilesCommand::adjustCommonHeader(){
410 if (commonHeaders.size() != 0) {
411 unsigned int magicN = commonHeaders[0].magicNumber;
412 string version = commonHeaders[0].version;
413 unsigned short headerLength = commonHeaders[0].headerLength;
414 unsigned short keyLength = commonHeaders[0].keyLength;
415 unsigned short numFlows = commonHeaders[0].numFlowsPerRead;
416 int flowCode = commonHeaders[0].flogramFormatCode;
417 string flowChars = commonHeaders[0].flowChars;
418 string keySeq = commonHeaders[0].keySequence;
420 for (int i = 1; i < commonHeaders.size(); i++) {
421 if (commonHeaders[i].magicNumber != magicN) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Magic numbers do not match. " + filenames[0] + " magic number is " + toString(commonHeaders[0].magicNumber) + ", but " + filenames[i] + " magic number is " + toString(commonHeaders[i].magicNumber) + ".\n"); }
422 if (commonHeaders[i].version != version) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Versions do not match. " + filenames[0] + " version is " + commonHeaders[0].version + ", but " + filenames[i] + " version is " + commonHeaders[i].version + ".\n"); }
423 if (commonHeaders[i].headerLength != headerLength) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Header lengths do not match. " + filenames[0] + " header length is " + toString(commonHeaders[0].headerLength) + ", but " + filenames[i] + " header length is " + toString(commonHeaders[i].headerLength) + ".\n"); }
424 if (commonHeaders[i].keyLength != keyLength) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Key Lengths do not match. " + filenames[0] + " Key length is " + toString(commonHeaders[0].keyLength) + ", but " + filenames[i] + " key length is " + toString(commonHeaders[i].keyLength) + ".\n"); }
425 if (commonHeaders[i].numFlowsPerRead != numFlows) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Number of flows per read do not match. " + filenames[0] + " number of flows is " + toString(commonHeaders[0].numFlowsPerRead) + ", but " + filenames[i] + " number of flows is " + toString(commonHeaders[i].numFlowsPerRead) + ".\n"); }
426 if (commonHeaders[i].flogramFormatCode != flowCode) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Flow format codes do not match. " + filenames[0] + " Flow format code is " + toString(commonHeaders[0].flogramFormatCode) + ", but " + filenames[i] + " flow format code is " + toString(commonHeaders[i].flogramFormatCode) + ".\n"); }
427 if (commonHeaders[i].flowChars != flowChars) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Flow characters do not match. " + filenames[0] + " Flow characters are " + commonHeaders[0].flowChars + ", but " + filenames[i] + " flow characters are " + commonHeaders[i].flowChars + ".\n"); }
428 if (commonHeaders[i].keySequence != keySeq) { okay = false; m->mothurOut("[ERROR]: merge issue with common headers. Key sequences do not match. " + filenames[0] + " Key sequence is " + commonHeaders[0].keySequence + ", but " + filenames[i] + " key sequence is " + commonHeaders[i].keySequence + ".\n"); }
430 }else { m->control_pressed = true; return 0; } //should never get here
432 if (!okay) { m->control_pressed = true; return 0; }
434 string endian = m->findEdianness();
435 char* mybuffer = new char[4];
437 m->openInputFileBinary(currentFileName, in);
442 m->openOutputFileBinaryAppend(outputFileHeader, out);
443 out.write(mybuffer, in.gcount());
447 mybuffer = new char[4];
449 out.write(mybuffer, in.gcount());
453 mybuffer = new char[8];
455 unsigned long long offset = 0;
456 char* thisbuffer = new char[8];
457 thisbuffer[0] = (offset >> 56) & 0xFF;
458 thisbuffer[1] = (offset >> 48) & 0xFF;
459 thisbuffer[2] = (offset >> 40) & 0xFF;
460 thisbuffer[3] = (offset >> 32) & 0xFF;
461 thisbuffer[4] = (offset >> 24) & 0xFF;
462 thisbuffer[5] = (offset >> 16) & 0xFF;
463 thisbuffer[6] = (offset >> 8) & 0xFF;
464 thisbuffer[7] = offset & 0xFF;
465 out.write(thisbuffer, 8);
470 mybuffer = new char[4];
473 char* thisbuffer2 = new char[4];
474 thisbuffer2[0] = (offset >> 24) & 0xFF;
475 thisbuffer2[1] = (offset >> 16) & 0xFF;
476 thisbuffer2[2] = (offset >> 8) & 0xFF;
477 thisbuffer2[3] = offset & 0xFF;
478 out.write(thisbuffer2, 4);
479 delete[] thisbuffer2;
483 mybuffer = new char[4];
486 thisbuffer2 = new char[4];
487 if (endian == "BIG_ENDIAN") {
488 thisbuffer2[0] = (numTotalReads >> 24) & 0xFF;
489 thisbuffer2[1] = (numTotalReads >> 16) & 0xFF;
490 thisbuffer2[2] = (numTotalReads >> 8) & 0xFF;
491 thisbuffer2[3] = numTotalReads & 0xFF;
493 thisbuffer2[0] = numTotalReads & 0xFF;
494 thisbuffer2[1] = (numTotalReads >> 8) & 0xFF;
495 thisbuffer2[2] = (numTotalReads >> 16) & 0xFF;
496 thisbuffer2[3] = (numTotalReads >> 24) & 0xFF;
498 out.write(thisbuffer2, 4);
499 delete[] thisbuffer2;
503 mybuffer = new char[2];
505 out.write(mybuffer, in.gcount());
509 mybuffer = new char[2];
511 out.write(mybuffer, in.gcount());
514 //read number of flow reads
515 mybuffer = new char[2];
517 out.write(mybuffer, in.gcount());
521 mybuffer = new char[1];
523 out.write(mybuffer, in.gcount());
527 mybuffer = new char[commonHeaders[0].numFlowsPerRead];
528 in.read(mybuffer,commonHeaders[0].numFlowsPerRead);
529 out.write(mybuffer, in.gcount());
533 mybuffer = new char[commonHeaders[0].keyLength];
534 in.read(mybuffer,commonHeaders[0].keyLength);
535 out.write(mybuffer, in.gcount());
539 unsigned long long spotInFile = in.tellg();
540 unsigned long long spot = (spotInFile + 7)& ~7; // ~ inverts
543 mybuffer = new char[spot-spotInFile];
544 out.write(mybuffer, spot-spotInFile);
549 m->appendBinaryFiles(outputFile, outputFileHeader);
550 m->renameFile(outputFileHeader, outputFile);
551 m->mothurRemove(outputFileHeader);
556 catch(exception& e) {
557 m->errorOut(e, "MergeSfffilesCommand", "adjustCommonHeader");
561 //**********************************************************************************************************************
562 bool MergeSfffilesCommand::readSeqData(ifstream& in, seqRead& read, int numFlowReads, Header& header, ofstream& out){
564 unsigned long long startSpotInFile = in.tellg();
567 /*****************************************/
573 header.headerLength = be_int2(*(unsigned short *)(&buffer));
578 header.nameLength = be_int2(*(unsigned short *)(&buffer2));
583 header.numBases = be_int4(*(unsigned int *)(&buffer3));
586 //read clip qual left
589 header.clipQualLeft = be_int2(*(unsigned short *)(&buffer4));
590 header.clipQualLeft = 5;
593 //read clip qual right
596 header.clipQualRight = be_int2(*(unsigned short *)(&buffer5));
599 //read clipAdapterLeft
602 header.clipAdapterLeft = be_int2(*(unsigned short *)(&buffer6));
605 //read clipAdapterRight
608 header.clipAdapterRight = be_int2(*(unsigned short *)(&buffer7));
612 char* tempBuffer = new char[header.nameLength];
613 in.read(&(*tempBuffer), header.nameLength);
614 header.name = tempBuffer;
615 if (header.name.length() > header.nameLength) { header.name = header.name.substr(0, header.nameLength); }
620 unsigned long long spotInFile = in.tellg();
621 unsigned long long spot = (spotInFile + 7)& ~7;
624 /*****************************************/
628 read.flowgram.resize(numFlowReads);
629 for (int i = 0; i < numFlowReads; i++) {
632 read.flowgram[i] = be_int2(*(unsigned short *)(&buffer));
636 read.flowIndex.resize(header.numBases);
637 for (int i = 0; i < header.numBases; i++) {
640 read.flowIndex[i] = be_int1(*(unsigned char *)(&temp));
644 char* tempBuffer6 = new char[header.numBases];
645 in.read(&(*tempBuffer6), header.numBases);
646 read.bases = tempBuffer6;
647 if (read.bases.length() > header.numBases) { read.bases = read.bases.substr(0, header.numBases); }
648 delete[] tempBuffer6;
651 read.qualScores.resize(header.numBases);
652 for (int i = 0; i < header.numBases; i++) {
655 read.qualScores[i] = be_int1(*(unsigned char *)(&temp));
659 spotInFile = in.tellg();
660 spot = (spotInFile + 7)& ~7;
664 mybuffer = new char [spot-startSpotInFile];
667 m->openInputFileBinary(currentFileName, in2);
668 in2.seekg(startSpotInFile);
669 in2.read(mybuffer,spot-startSpotInFile);
671 out.write(mybuffer, in2.gcount());
678 m->mothurOut("Error reading."); m->mothurOutEndLine();
681 if (in.eof()) { return true; }
685 catch(exception& e) {
686 m->errorOut(e, "MergeSfffilesCommand", "readSeqData");
690 //**********************************************************************************************************************
691 bool MergeSfffilesCommand::sanityCheck(Header& header, seqRead& read) {
694 string message = "[WARNING]: Your sff file may be corrupted! Sequence: " + header.name + "\n";
696 if (header.clipQualLeft > read.bases.length()) {
697 okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
699 if (header.clipQualRight > read.bases.length()) {
700 okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
702 if (header.clipQualLeft > read.qualScores.size()) {
703 okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
705 if (header.clipQualRight > read.qualScores.size()) {
706 okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
710 m->mothurOut(message); m->mothurOutEndLine();
715 catch(exception& e) {
716 m->errorOut(e, "MergeSfffilesCommand", "sanityCheck");
720 //**********************************************************************************************************************
721 int MergeSfffilesCommand::readFile(){
727 m->openInputFile(file, in);
731 if (m->control_pressed) { return 0; }
733 in >> filename; m->gobble(in);
735 if (m->debug) { m->mothurOut("[DEBUG]: filename = " + filename + ".\n"); }
737 //check to make sure both are able to be opened
739 int openForward = m->openInputFile(filename, in2, "noerror");
741 //if you can't open it, try default location
742 if (openForward == 1) {
743 if (m->getDefaultPath() != "") { //default path is set
744 string tryPath = m->getDefaultPath() + m->getSimpleName(filename);
745 m->mothurOut("Unable to open " + filename + ". Trying default " + tryPath); m->mothurOutEndLine();
747 openForward = m->openInputFile(tryPath, in3, "noerror");
753 //if you can't open it, try output location
754 if (openForward == 1) {
755 if (m->getOutputDir() != "") { //default path is set
756 string tryPath = m->getOutputDir() + m->getSimpleName(filename);
757 m->mothurOut("Unable to open " + filename + ". Trying output directory " + tryPath); m->mothurOutEndLine();
759 openForward = m->openInputFile(tryPath, in4, "noerror");
765 if (openForward == 1) { //can't find it
766 m->mothurOut("[WARNING]: can't find " + filename + ", ignoring.\n");
767 }else{ filenames.push_back(filename); }
774 catch(exception& e) {
775 m->errorOut(e, "MergeSfffilesCommand", "readFileNames");
779 //**********************************************************************************************************************