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 pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
18 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
20 vector<string> myArray;
21 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
25 m->errorOut(e, "MergeSfffilesCommand", "setParameters");
29 //**********************************************************************************************************************
30 string MergeSfffilesCommand::getHelpString(){
32 string helpString = "";
33 helpString += "The merge.sfffiles command reads a sff set of files or a file containing a list of sff files and merges the individual files into a single sff file.\n";
34 helpString += "The merge.sfffiles command parameters are sff and file. sff or file is required. \n";
35 helpString += "The sff parameter allows you to enter the sff list of sff files separated by -'s.\n";
36 helpString += "The file parameter allows you to provide a file containing a list of sff files to merge. \n";
37 helpString += "Example sffinfo(sff=mySffFile.sff-mySecond.sff).\n";
38 helpString += "Note: No spaces between parameter labels (i.e. sff), '=' and parameters (i.e.yourSffFileName).\n";
42 m->errorOut(e, "MergeSfffilesCommand", "getHelpString");
47 //**********************************************************************************************************************
48 string MergeSfffilesCommand::getOutputPattern(string type) {
52 if (type == "sff") { pattern = "[filename],merge.sff"; }
53 else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true; }
58 m->errorOut(e, "MergeSfffilesCommand", "getOutputPattern");
62 //**********************************************************************************************************************
63 MergeSfffilesCommand::MergeSfffilesCommand(){
65 abort = true; calledHelp = true;
67 vector<string> tempOutNames;
68 outputTypes["sff"] = tempOutNames;
71 m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
75 //**********************************************************************************************************************
77 MergeSfffilesCommand::MergeSfffilesCommand(string option) {
79 abort = false; calledHelp = false;
81 //allow user to run help
82 if(option == "help") { help(); abort = true; calledHelp = true; }
83 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
86 //valid paramters for this command
87 vector<string> myArray = setParameters();
89 OptionParser parser(option);
90 map<string, string> parameters = parser.getParameters();
91 map<string,string>::iterator it;
93 ValidParameters validParameter;
94 //check to make sure all parameters are valid for command
95 for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) {
96 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
99 //initialize outputTypes
100 vector<string> tempOutNames;
101 outputTypes["sff"] = tempOutNames;
103 //if the user changes the output directory command factory will send this info to us in the output parameter
104 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){ outputDir = ""; }
106 //if the user changes the input directory command factory will send this info to us in the output parameter
107 string inputDir = validParameter.validFile(parameters, "inputdir", false); if (inputDir == "not found"){ inputDir = ""; }
109 it = parameters.find("file");
110 //user has given a template file
111 if(it != parameters.end()){
112 string path = m->hasPath(it->second);
113 //if the user has not given a path then, add inputdir. else leave path alone.
114 if (path == "") { parameters["file"] = inputDir + it->second; }
118 sffFilename = validParameter.validFile(parameters, "sff", false);
119 if (sffFilename == "not found") { sffFilename = ""; }
121 m->splitAtDash(sffFilename, filenames);
123 //go through files and make sure they are good, if not, then disregard them
124 for (int i = 0; i < filenames.size(); i++) {
126 if (filenames[i] == "current") {
127 filenames[i] = m->getSFFFile();
128 if (filenames[i] != "") { m->mothurOut("Using " + filenames[i] + " as input file for the sff parameter where you had given current."); m->mothurOutEndLine(); }
130 m->mothurOut("You have no current sfffile, ignoring current."); m->mothurOutEndLine(); ignore=true;
131 //erase from file list
132 filenames.erase(filenames.begin()+i);
138 if (inputDir != "") {
139 string path = m->hasPath(filenames[i]);
140 //if the user has not given a path then, add inputdir. else leave path alone.
141 if (path == "") { filenames[i] = inputDir + filenames[i]; }
145 int ableToOpen = m->openInputFile(filenames[i], in, "noerror");
147 //if you can't open it, try default location
148 if (ableToOpen == 1) {
149 if (m->getDefaultPath() != "") { //default path is set
150 string tryPath = m->getDefaultPath() + m->getSimpleName(filenames[i]);
151 m->mothurOut("Unable to open " + filenames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
153 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
155 filenames[i] = tryPath;
159 //if you can't open it, try default location
160 if (ableToOpen == 1) {
161 if (m->getOutputDir() != "") { //default path is set
162 string tryPath = m->getOutputDir() + m->getSimpleName(filenames[i]);
163 m->mothurOut("Unable to open " + filenames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
165 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
167 filenames[i] = tryPath;
173 if (ableToOpen == 1) {
174 m->mothurOut("Unable to open " + filenames[i] + ". It will be disregarded."); m->mothurOutEndLine();
175 //erase from file list
176 filenames.erase(filenames.begin()+i);
178 }else { m->setSFFFile(filenames[i]); }
183 file = validParameter.validFile(parameters, "file", true);
184 if (file == "not open") { abort = true; }
185 else if (file == "not found") { file = ""; }
187 if ((file == "") && (filenames.size() == 0)) {
188 m->mothurOut("[ERROR]: no valid files."); m->mothurOutEndLine(); abort = true;
191 if ((file != "") && (filenames.size() != 0)) { //both are given
192 m->mothurOut("[ERROR]: cannot use file option and sff option at the same time, choose one."); m->mothurOutEndLine(); abort = true;
197 catch(exception& e) {
198 m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
202 //**********************************************************************************************************************
203 int MergeSfffilesCommand::execute(){
205 if (abort == true) { if (calledHelp) { return 0; } return 2; }
207 map<string, string> variables;
209 string thisOutputDir = outputDir;
210 if (outputDir == "") { thisOutputDir += m->hasPath(file); }
211 variables["[filename]"] = thisOutputDir + m->getRootName(m->getSimpleName(file));
214 string thisOutputDir = outputDir;
215 if (outputDir == "") { thisOutputDir += m->hasPath(filenames[0]); }
216 variables["[filename]"] = thisOutputDir + "mergedSff";
219 outputFile = getOutputFileName("sff",variables);
220 m->openOutputFile(outputFile, out);
221 outputNames.push_back(outputFile); outputTypes["sff"].push_back(outputFile);
222 outputFileHeader = outputFile + ".headers";
225 for (int s = 0; s < filenames.size(); s++) {
227 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
229 int start = time(NULL);
231 filenames[s] = m->getFullPathName(filenames[s]);
232 m->mothurOut("\nMerging info from " + filenames[s] + " ..." ); m->mothurOutEndLine();
234 int numReads = mergeSffInfo(filenames[s], out);
236 m->mothurOut("It took " + toString(time(NULL) - start) + " secs to merge " + toString(numReads) + ".\n");
240 //create new common header and add to merged file
241 adjustCommonHeader();
243 if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); } return 0; }
245 //set sff file as new current sff file
247 itTypes = outputTypes.find("sff");
248 if (itTypes != outputTypes.end()) {
249 if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSFFFile(current); }
252 //report output filenames
253 m->mothurOutEndLine();
254 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
255 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
256 m->mothurOutEndLine();
260 catch(exception& e) {
261 m->errorOut(e, "MergeSfffilesCommand", "execute");
265 //**********************************************************************************************************************
266 int MergeSfffilesCommand::mergeSffInfo(string input, ofstream& out){
268 currentFileName = input;
271 m->openInputFileBinary(input, in);
274 readCommonHeader(in, header);
278 //check magic number and version
279 if (header.magicNumber != 779314790) { m->mothurOut("Magic Number is not correct, not a valid .sff file"); m->mothurOutEndLine(); return count; }
280 if (header.version != "0001") { m->mothurOut("Version is not supported, only support version 0001."); m->mothurOutEndLine(); return count; }
282 //save for adjustHeader sanity check
283 commonHeaders.push_back(header);
285 //read through the sff file
289 seqRead read; Header readheader;
290 readSeqData(in, read, header.numFlowsPerRead, readheader, out);
292 bool okay = sanityCheck(readheader, read);
293 if (!okay) { break; }
298 if((count+1) % 10000 == 0){ m->mothurOut(toString(count+1)); m->mothurOutEndLine(); }
300 if (m->control_pressed) { count = 0; break; }
302 if (count >= header.numReads) { break; }
306 if (!m->control_pressed) { if((count) % 10000 != 0){ m->mothurOut(toString(count)); m->mothurOutEndLine(); } }
312 catch(exception& e) {
313 m->errorOut(e, "MergeSfffilesCommand", "mergeSffInfo");
317 //**********************************************************************************************************************
318 int MergeSfffilesCommand::readCommonHeader(ifstream& in, CommonHeader& header){
326 header.magicNumber = be_int4(*(unsigned int *)(&buffer));
332 for (int i = 0; i < 4; i++) { header.version += toString((int)(buffer9[i])); }
337 header.indexOffset = be_int8(*(unsigned long long *)(&buffer2));
342 header.indexLength = be_int4(*(unsigned int *)(&buffer3));
347 header.numReads = be_int4(*(unsigned int *)(&buffer4));
349 if (m->debug) { m->mothurOut("[DEBUG]: numReads = " + toString(header.numReads) + "\n"); }
354 header.headerLength = be_int2(*(unsigned short *)(&buffer5));
359 header.keyLength = be_int2(*(unsigned short *)(&buffer6));
361 //read number of flow reads
364 header.numFlowsPerRead = be_int2(*(unsigned short *)(&buffer7));
369 header.flogramFormatCode = (int)(buffer8[0]);
372 char* tempBuffer = new char[header.numFlowsPerRead];
373 in.read(&(*tempBuffer), header.numFlowsPerRead);
374 header.flowChars = tempBuffer;
375 if (header.flowChars.length() > header.numFlowsPerRead) { header.flowChars = header.flowChars.substr(0, header.numFlowsPerRead); }
379 char* tempBuffer2 = new char[header.keyLength];
380 in.read(&(*tempBuffer2), header.keyLength);
381 header.keySequence = tempBuffer2;
382 if (header.keySequence.length() > header.keyLength) { header.keySequence = header.keySequence.substr(0, header.keyLength); }
383 delete[] tempBuffer2;
386 unsigned long long spotInFile = in.tellg();
387 unsigned long long spot = (spotInFile + 7)& ~7; // ~ inverts
391 m->mothurOut("Error reading sff common header."); m->mothurOutEndLine();
397 catch(exception& e) {
398 m->errorOut(e, "MergeSfffilesCommand", "readCommonHeader");
402 //**********************************************************************************************************************
403 int MergeSfffilesCommand::adjustCommonHeader(){
407 if (commonHeaders.size() != 0) {
408 unsigned int magicN = commonHeaders[0].magicNumber;
409 string version = commonHeaders[0].version;
410 unsigned short headerLength = commonHeaders[0].headerLength;
411 unsigned short keyLength = commonHeaders[0].keyLength;
412 unsigned short numFlows = commonHeaders[0].numFlowsPerRead;
413 int flowCode = commonHeaders[0].flogramFormatCode;
414 string flowChars = commonHeaders[0].flowChars;
415 string keySeq = commonHeaders[0].keySequence;
417 for (int i = 1; i < commonHeaders.size(); i++) {
418 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"); }
419 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"); }
420 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"); }
421 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"); }
422 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"); }
423 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"); }
424 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"); }
425 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"); }
427 }else { m->control_pressed = true; return 0; } //should never get here
429 if (!okay) { m->control_pressed = true; return 0; }
431 string endian = m->findEdianness();
432 char* mybuffer = new char[4];
434 m->openInputFileBinary(currentFileName, in);
439 m->openOutputFileBinaryAppend(outputFileHeader, out);
440 out.write(mybuffer, in.gcount());
444 mybuffer = new char[4];
446 out.write(mybuffer, in.gcount());
450 mybuffer = new char[8];
452 unsigned long long offset = 0;
453 char* thisbuffer = new char[8];
454 thisbuffer[0] = (offset >> 56) & 0xFF;
455 thisbuffer[1] = (offset >> 48) & 0xFF;
456 thisbuffer[2] = (offset >> 40) & 0xFF;
457 thisbuffer[3] = (offset >> 32) & 0xFF;
458 thisbuffer[4] = (offset >> 24) & 0xFF;
459 thisbuffer[5] = (offset >> 16) & 0xFF;
460 thisbuffer[6] = (offset >> 8) & 0xFF;
461 thisbuffer[7] = offset & 0xFF;
462 out.write(thisbuffer, 8);
467 mybuffer = new char[4];
470 char* thisbuffer2 = new char[4];
471 thisbuffer2[0] = (offset >> 24) & 0xFF;
472 thisbuffer2[1] = (offset >> 16) & 0xFF;
473 thisbuffer2[2] = (offset >> 8) & 0xFF;
474 thisbuffer2[3] = offset & 0xFF;
475 out.write(thisbuffer2, 4);
476 delete[] thisbuffer2;
480 mybuffer = new char[4];
483 thisbuffer2 = new char[4];
484 if (endian == "BIG_ENDIAN") {
485 thisbuffer2[0] = (numTotalReads >> 24) & 0xFF;
486 thisbuffer2[1] = (numTotalReads >> 16) & 0xFF;
487 thisbuffer2[2] = (numTotalReads >> 8) & 0xFF;
488 thisbuffer2[3] = numTotalReads & 0xFF;
490 thisbuffer2[0] = numTotalReads & 0xFF;
491 thisbuffer2[1] = (numTotalReads >> 8) & 0xFF;
492 thisbuffer2[2] = (numTotalReads >> 16) & 0xFF;
493 thisbuffer2[3] = (numTotalReads >> 24) & 0xFF;
495 out.write(thisbuffer2, 4);
496 delete[] thisbuffer2;
500 mybuffer = new char[2];
502 out.write(mybuffer, in.gcount());
506 mybuffer = new char[2];
508 out.write(mybuffer, in.gcount());
511 //read number of flow reads
512 mybuffer = new char[2];
514 out.write(mybuffer, in.gcount());
518 mybuffer = new char[1];
520 out.write(mybuffer, in.gcount());
524 mybuffer = new char[commonHeaders[0].numFlowsPerRead];
525 in.read(mybuffer,commonHeaders[0].numFlowsPerRead);
526 out.write(mybuffer, in.gcount());
530 mybuffer = new char[commonHeaders[0].keyLength];
531 in.read(mybuffer,commonHeaders[0].keyLength);
532 out.write(mybuffer, in.gcount());
536 unsigned long long spotInFile = in.tellg();
537 unsigned long long spot = (spotInFile + 7)& ~7; // ~ inverts
540 mybuffer = new char[spot-spotInFile];
541 out.write(mybuffer, spot-spotInFile);
546 m->appendBinaryFiles(outputFile, outputFileHeader);
547 m->renameFile(outputFileHeader, outputFile);
548 m->mothurRemove(outputFileHeader);
553 catch(exception& e) {
554 m->errorOut(e, "MergeSfffilesCommand", "adjustCommonHeader");
558 //**********************************************************************************************************************
559 bool MergeSfffilesCommand::readSeqData(ifstream& in, seqRead& read, int numFlowReads, Header& header, ofstream& out){
561 unsigned long long startSpotInFile = in.tellg();
564 /*****************************************/
570 header.headerLength = be_int2(*(unsigned short *)(&buffer));
575 header.nameLength = be_int2(*(unsigned short *)(&buffer2));
580 header.numBases = be_int4(*(unsigned int *)(&buffer3));
583 //read clip qual left
586 header.clipQualLeft = be_int2(*(unsigned short *)(&buffer4));
587 header.clipQualLeft = 5;
590 //read clip qual right
593 header.clipQualRight = be_int2(*(unsigned short *)(&buffer5));
596 //read clipAdapterLeft
599 header.clipAdapterLeft = be_int2(*(unsigned short *)(&buffer6));
602 //read clipAdapterRight
605 header.clipAdapterRight = be_int2(*(unsigned short *)(&buffer7));
609 char* tempBuffer = new char[header.nameLength];
610 in.read(&(*tempBuffer), header.nameLength);
611 header.name = tempBuffer;
612 if (header.name.length() > header.nameLength) { header.name = header.name.substr(0, header.nameLength); }
617 unsigned long long spotInFile = in.tellg();
618 unsigned long long spot = (spotInFile + 7)& ~7;
621 /*****************************************/
625 read.flowgram.resize(numFlowReads);
626 for (int i = 0; i < numFlowReads; i++) {
629 read.flowgram[i] = be_int2(*(unsigned short *)(&buffer));
633 read.flowIndex.resize(header.numBases);
634 for (int i = 0; i < header.numBases; i++) {
637 read.flowIndex[i] = be_int1(*(unsigned char *)(&temp));
641 char* tempBuffer6 = new char[header.numBases];
642 in.read(&(*tempBuffer6), header.numBases);
643 read.bases = tempBuffer6;
644 if (read.bases.length() > header.numBases) { read.bases = read.bases.substr(0, header.numBases); }
645 delete[] tempBuffer6;
648 read.qualScores.resize(header.numBases);
649 for (int i = 0; i < header.numBases; i++) {
652 read.qualScores[i] = be_int1(*(unsigned char *)(&temp));
656 spotInFile = in.tellg();
657 spot = (spotInFile + 7)& ~7;
661 mybuffer = new char [spot-startSpotInFile];
664 m->openInputFileBinary(currentFileName, in2);
665 in2.seekg(startSpotInFile);
666 in2.read(mybuffer,spot-startSpotInFile);
668 out.write(mybuffer, in2.gcount());
675 m->mothurOut("Error reading."); m->mothurOutEndLine();
678 if (in.eof()) { return true; }
682 catch(exception& e) {
683 m->errorOut(e, "MergeSfffilesCommand", "readSeqData");
687 //**********************************************************************************************************************
688 bool MergeSfffilesCommand::sanityCheck(Header& header, seqRead& read) {
691 string message = "[WARNING]: Your sff file may be corrupted! Sequence: " + header.name + "\n";
693 if (header.clipQualLeft > read.bases.length()) {
694 okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
696 if (header.clipQualRight > read.bases.length()) {
697 okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
699 if (header.clipQualLeft > read.qualScores.size()) {
700 okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
702 if (header.clipQualRight > read.qualScores.size()) {
703 okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
707 m->mothurOut(message); m->mothurOutEndLine();
712 catch(exception& e) {
713 m->errorOut(e, "MergeSfffilesCommand", "sanityCheck");
717 //**********************************************************************************************************************
718 int MergeSfffilesCommand::readFile(){
724 m->openInputFile(file, in);
728 if (m->control_pressed) { return 0; }
730 in >> filename; m->gobble(in);
732 if (m->debug) { m->mothurOut("[DEBUG]: filename = " + filename + ".\n"); }
734 //check to make sure both are able to be opened
736 int openForward = m->openInputFile(filename, in2, "noerror");
738 //if you can't open it, try default location
739 if (openForward == 1) {
740 if (m->getDefaultPath() != "") { //default path is set
741 string tryPath = m->getDefaultPath() + m->getSimpleName(filename);
742 m->mothurOut("Unable to open " + filename + ". Trying default " + tryPath); m->mothurOutEndLine();
744 openForward = m->openInputFile(tryPath, in3, "noerror");
750 //if you can't open it, try output location
751 if (openForward == 1) {
752 if (m->getOutputDir() != "") { //default path is set
753 string tryPath = m->getOutputDir() + m->getSimpleName(filename);
754 m->mothurOut("Unable to open " + filename + ". Trying output directory " + tryPath); m->mothurOutEndLine();
756 openForward = m->openInputFile(tryPath, in4, "noerror");
762 if (openForward == 1) { //can't find it
763 m->mothurOut("[WARNING]: can't find " + filename + ", ignoring.\n");
764 }else{ filenames.push_back(filename); }
771 catch(exception& e) {
772 m->errorOut(e, "MergeSfffilesCommand", "readFileNames");
776 //**********************************************************************************************************************