]> git.donarmstrong.com Git - mothur.git/blobdiff - mergesfffilecommand.cpp
added mergesfffiles command. added current directories to get.current commands output...
[mothur.git] / mergesfffilecommand.cpp
diff --git a/mergesfffilecommand.cpp b/mergesfffilecommand.cpp
new file mode 100644 (file)
index 0000000..056d85c
--- /dev/null
@@ -0,0 +1,780 @@
+//
+//  mergesfffilecommand.cpp
+//  Mothur
+//
+//  Created by Sarah Westcott on 1/31/14.
+//  Copyright (c) 2014 Schloss Lab. All rights reserved.
+//
+
+#include "mergesfffilecommand.h"
+#include "endiannessmacros.h"
+
+//**********************************************************************************************************************
+vector<string> MergeSfffilesCommand::setParameters(){
+       try {
+               CommandParameter psff("sff", "InputTypes", "", "", "sffFile", "sffFile", "none","sff",false,false); parameters.push_back(psff);
+        CommandParameter pfile("file", "InputTypes", "", "", "sffFile", "sffFile", "none","sff",false,false); parameters.push_back(pfile);
+               CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
+               CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
+               
+               vector<string> myArray;
+               for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
+               return myArray;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "setParameters");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+string MergeSfffilesCommand::getHelpString(){
+       try {
+               string helpString = "";
+               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";
+               helpString += "The merge.sfffiles command parameters are sff and file. sff or file is required. \n";
+               helpString += "The sff parameter allows you to enter the sff list of sff files separated by -'s.\n";
+               helpString += "The file parameter allows you to provide a file containing a list of sff files to merge.  \n";
+               helpString += "Example sffinfo(sff=mySffFile.sff-mySecond.sff).\n";
+               helpString += "Note: No spaces between parameter labels (i.e. sff), '=' and parameters (i.e.yourSffFileName).\n";
+               return helpString;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "getHelpString");
+               exit(1);
+       }
+}
+
+//**********************************************************************************************************************
+string MergeSfffilesCommand::getOutputPattern(string type) {
+    try {
+        string pattern = "";
+        
+        if (type == "sff")            {   pattern =  "[filename],merge.sff";   }
+        else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
+        
+        return pattern;
+    }
+    catch(exception& e) {
+        m->errorOut(e, "MergeSfffilesCommand", "getOutputPattern");
+        exit(1);
+    }
+}
+//**********************************************************************************************************************
+MergeSfffilesCommand::MergeSfffilesCommand(){
+       try {
+               abort = true; calledHelp = true;
+               setParameters();
+               vector<string> tempOutNames;
+        outputTypes["sff"] = tempOutNames;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+
+MergeSfffilesCommand::MergeSfffilesCommand(string option)  {
+       try {
+               abort = false; calledHelp = false;
+               
+               //allow user to run help
+               if(option == "help") { help(); abort = true; calledHelp = true; }
+               else if(option == "citation") { citation(); abort = true; calledHelp = true;}
+               
+               else {
+                       //valid paramters for this command
+                       vector<string> myArray = setParameters();
+                       
+                       OptionParser parser(option);
+                       map<string, string> parameters = parser.getParameters();
+            map<string,string>::iterator it;
+                       
+                       ValidParameters validParameter;
+                       //check to make sure all parameters are valid for command
+                       for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) {
+                               if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
+                       }
+                       
+                       //initialize outputTypes
+                       vector<string> tempOutNames;
+            outputTypes["sff"] = tempOutNames;
+                       
+                       //if the user changes the output directory command factory will send this info to us in the output parameter
+                       outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = "";         }
+                       
+                       //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);        if (inputDir == "not found"){ inputDir = "";          }
+            else {
+                it = parameters.find("file");
+                               //user has given a template file
+                               if(it != parameters.end()){
+                                       string path = m->hasPath(it->second);
+                                       //if the user has not given a path then, add inputdir. else leave path alone.
+                                       if (path == "") {       parameters["file"] = inputDir + it->second;             }
+                               }
+            }
+            
+                       sffFilename = validParameter.validFile(parameters, "sff", false);
+                       if (sffFilename == "not found") { sffFilename = "";  }
+                       else {
+                               m->splitAtDash(sffFilename, filenames);
+                               
+                               //go through files and make sure they are good, if not, then disregard them
+                               for (int i = 0; i < filenames.size(); i++) {
+                                       bool ignore = false;
+                                       if (filenames[i] == "current") {
+                                               filenames[i] = m->getSFFFile();
+                                               if (filenames[i] != "") {  m->mothurOut("Using " + filenames[i] + " as input file for the sff parameter where you had given current."); m->mothurOutEndLine(); }
+                                               else {
+                                                       m->mothurOut("You have no current sfffile, ignoring current."); m->mothurOutEndLine(); ignore=true;
+                                                       //erase from file list
+                                                       filenames.erase(filenames.begin()+i);
+                                                       i--;
+                                               }
+                                       }
+                                       
+                                       if (!ignore) {
+                                               if (inputDir != "") {
+                                                       string path = m->hasPath(filenames[i]);
+                                                       //if the user has not given a path then, add inputdir. else leave path alone.
+                                                       if (path == "") {       filenames[i] = inputDir + filenames[i];         }
+                                               }
+                        
+                                               ifstream in;
+                                               int ableToOpen = m->openInputFile(filenames[i], in, "noerror");
+                        
+                                               //if you can't open it, try default location
+                                               if (ableToOpen == 1) {
+                                                       if (m->getDefaultPath() != "") { //default path is set
+                                                               string tryPath = m->getDefaultPath() + m->getSimpleName(filenames[i]);
+                                                               m->mothurOut("Unable to open " + filenames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
+                                                               ifstream in2;
+                                                               ableToOpen = m->openInputFile(tryPath, in2, "noerror");
+                                                               in2.close();
+                                                               filenames[i] = tryPath;
+                                                       }
+                                               }
+                                               
+                                               //if you can't open it, try default location
+                                               if (ableToOpen == 1) {
+                                                       if (m->getOutputDir() != "") { //default path is set
+                                                               string tryPath = m->getOutputDir() + m->getSimpleName(filenames[i]);
+                                                               m->mothurOut("Unable to open " + filenames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
+                                                               ifstream in2;
+                                                               ableToOpen = m->openInputFile(tryPath, in2, "noerror");
+                                                               in2.close();
+                                                               filenames[i] = tryPath;
+                                                       }
+                                               }
+                                               
+                                               in.close();
+                                               
+                                               if (ableToOpen == 1) {
+                                                       m->mothurOut("Unable to open " + filenames[i] + ". It will be disregarded."); m->mothurOutEndLine();
+                                                       //erase from file list
+                                                       filenames.erase(filenames.begin()+i);
+                                                       i--;
+                                               }else { m->setSFFFile(filenames[i]); }
+                                       }
+                               }
+                       }
+                       
+                       file = validParameter.validFile(parameters, "file", true);
+                       if (file == "not open") {  abort = true; }
+                       else if (file == "not found") { file = "";  }
+            
+            if ((file == "") && (filenames.size() == 0)) {
+                m->mothurOut("[ERROR]: no valid files."); m->mothurOutEndLine(); abort = true;
+            }
+            
+            if ((file != "") && (filenames.size() != 0)) { //both are given
+                m->mothurOut("[ERROR]: cannot use file option and sff option at the same time, choose one."); m->mothurOutEndLine(); abort = true;
+            }
+            
+               }
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "MergeSfffilesCommand");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+int MergeSfffilesCommand::execute(){
+       try {
+               if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
+        
+        map<string, string> variables;
+        if (file != "") {
+            string thisOutputDir = outputDir;
+            if (outputDir == "") {  thisOutputDir += m->hasPath(file);  }
+            variables["[filename]"] = thisOutputDir + m->getRootName(m->getSimpleName(file));
+            readFile();
+        }else {
+            string thisOutputDir = outputDir;
+            if (outputDir == "") {  thisOutputDir += m->hasPath(filenames[0]);  }
+            variables["[filename]"] = thisOutputDir + "mergedSff";
+        }
+        ofstream out;
+               outputFile = getOutputFileName("sff",variables);
+        m->openOutputFile(outputFile, out);
+        outputNames.push_back(outputFile); outputTypes["sff"].push_back(outputFile);
+        outputFileHeader = outputFile + ".headers";
+        numTotalReads = 0;
+        
+               for (int s = 0; s < filenames.size(); s++) {
+                       
+                       if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);        } return 0; }
+                       
+                       int start = time(NULL);
+                       
+            filenames[s] = m->getFullPathName(filenames[s]);
+                       m->mothurOut("\nMerging info from " + filenames[s] + " ..." ); m->mothurOutEndLine();
+            
+                       int numReads = mergeSffInfo(filenames[s], out);
+            
+                       m->mothurOut("It took " + toString(time(NULL) - start) + " secs to merge " + toString(numReads) + ".\n");
+               }
+        out.close();
+        
+        //create new common header and add to merged file
+        adjustCommonHeader();
+
+               if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);        } return 0; }
+               
+               //set sff file as new current sff file
+               string current = "";
+               itTypes = outputTypes.find("sff");
+               if (itTypes != outputTypes.end()) {
+                       if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSFFFile(current); }
+               }
+               
+               //report output filenames
+               m->mothurOutEndLine();
+               m->mothurOut("Output File Names: "); m->mothurOutEndLine();
+               for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
+               m->mothurOutEndLine();
+        
+               return 0;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "execute");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+int MergeSfffilesCommand::mergeSffInfo(string input, ofstream& out){
+       try {
+               currentFileName = input;
+        
+               ifstream in;
+               m->openInputFileBinary(input, in);
+               
+               CommonHeader header;
+               readCommonHeader(in, header);
+        
+               int count = 0;
+               
+               //check magic number and version
+               if (header.magicNumber != 779314790) { m->mothurOut("Magic Number is not correct, not a valid .sff file"); m->mothurOutEndLine(); return count; }
+               if (header.version != "0001") { m->mothurOut("Version is not supported, only support version 0001."); m->mothurOutEndLine(); return count; }
+               
+        //save for adjustHeader sanity check
+        commonHeaders.push_back(header);
+        
+               //read through the sff file
+               while (!in.eof()) {
+            
+                       //read data
+                       seqRead read;  Header readheader;
+            readSeqData(in, read, header.numFlowsPerRead, readheader, out);
+            
+            bool okay = sanityCheck(readheader, read);
+            if (!okay) { break; }
+                       
+                       count++;
+            
+                       //report progress
+                       if((count+1) % 10000 == 0){     m->mothurOut(toString(count+1)); m->mothurOutEndLine();         }
+            
+                       if (m->control_pressed) { count = 0; break;   }
+                       
+                       if (count >= header.numReads) { break; }
+               }
+               
+               //report progress
+               if (!m->control_pressed) {   if((count) % 10000 != 0){  m->mothurOut(toString(count)); m->mothurOutEndLine();           }  }
+               
+               in.close();
+               
+               return count;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "mergeSffInfo");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+int MergeSfffilesCommand::readCommonHeader(ifstream& in, CommonHeader& header){
+       try {
+        
+               if (!in.eof()) {
+            
+                       //read magic number
+                       char buffer[4];
+                       in.read(buffer, 4);
+                       header.magicNumber = be_int4(*(unsigned int *)(&buffer));
+            
+                       //read version
+                       char buffer9[4];
+                       in.read(buffer9, 4);
+                       header.version = "";
+                       for (int i = 0; i < 4; i++) {  header.version += toString((int)(buffer9[i]));  }
+            
+                       //read offset
+                       char buffer2 [8];
+                       in.read(buffer2, 8);
+                       header.indexOffset =  be_int8(*(unsigned long long *)(&buffer2));
+                       
+                       //read index length
+                       char buffer3 [4];
+                       in.read(buffer3, 4);
+                       header.indexLength =  be_int4(*(unsigned int *)(&buffer3));
+            
+                       //read num reads
+                       char buffer4 [4];
+                       in.read(buffer4, 4);
+                       header.numReads =  be_int4(*(unsigned int *)(&buffer4));
+            
+            if (m->debug) { m->mothurOut("[DEBUG]: numReads = " + toString(header.numReads) + "\n"); }
+            
+                       //read header length
+                       char buffer5 [2];
+                       in.read(buffer5, 2);
+                       header.headerLength =  be_int2(*(unsigned short *)(&buffer5));
+            
+                       //read key length
+                       char buffer6 [2];
+                       in.read(buffer6, 2);
+                       header.keyLength = be_int2(*(unsigned short *)(&buffer6));
+                       
+                       //read number of flow reads
+                       char buffer7 [2];
+                       in.read(buffer7, 2);
+                       header.numFlowsPerRead =  be_int2(*(unsigned short *)(&buffer7));
+            
+                       //read format code
+                       char buffer8 [1];
+                       in.read(buffer8, 1);
+                       header.flogramFormatCode = (int)(buffer8[0]);
+                       
+                       //read flow chars
+                       char* tempBuffer = new char[header.numFlowsPerRead];
+                       in.read(&(*tempBuffer), header.numFlowsPerRead);
+                       header.flowChars = tempBuffer;
+                       if (header.flowChars.length() > header.numFlowsPerRead) { header.flowChars = header.flowChars.substr(0, header.numFlowsPerRead);  }
+                       delete[] tempBuffer;
+                       
+                       //read key
+                       char* tempBuffer2 = new char[header.keyLength];
+                       in.read(&(*tempBuffer2), header.keyLength);
+                       header.keySequence = tempBuffer2;
+                       if (header.keySequence.length() > header.keyLength) { header.keySequence = header.keySequence.substr(0, header.keyLength);  }
+                       delete[] tempBuffer2;
+                       
+                       /* Pad to 8 chars */
+                       unsigned long long spotInFile = in.tellg();
+                       unsigned long long spot = (spotInFile + 7)& ~7;  // ~ inverts
+                       in.seekg(spot);
+            
+        }else{
+                       m->mothurOut("Error reading sff common header."); m->mothurOutEndLine();
+               }
+        
+               return 0;
+        
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "readCommonHeader");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+int MergeSfffilesCommand::adjustCommonHeader(){
+       try {
+        //sanity check
+        bool okay = true;
+        if (commonHeaders.size() != 0) {
+            unsigned int magicN = commonHeaders[0].magicNumber;
+            string version = commonHeaders[0].version;
+            unsigned short headerLength = commonHeaders[0].headerLength;
+            unsigned short keyLength = commonHeaders[0].keyLength;
+            unsigned short numFlows = commonHeaders[0].numFlowsPerRead;
+            int flowCode = commonHeaders[0].flogramFormatCode;
+            string flowChars = commonHeaders[0].flowChars;
+            string keySeq = commonHeaders[0].keySequence;
+            
+            for (int i = 1; i < commonHeaders.size(); i++) {
+                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");  }
+                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");     }
+                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");    }
+                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");    }
+                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");     }
+                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");    }
+                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");    }
+                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");     }
+            }
+        }else { m->control_pressed = true; return 0; } //should never get here
+        
+        if (!okay) { m->control_pressed = true; return 0; }
+        
+        string endian = m->findEdianness();
+        char* mybuffer = new char[4];
+        ifstream in;
+        m->openInputFileBinary(currentFileName, in);
+        
+        //magic number
+        in.read(mybuffer,4);
+        ofstream out;
+        m->openOutputFileBinaryAppend(outputFileHeader, out);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //version
+        mybuffer = new char[4];
+        in.read(mybuffer,4);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //offset
+        mybuffer = new char[8];
+        in.read(mybuffer,8);
+        unsigned long long offset = 0;
+        char* thisbuffer = new char[8];
+        thisbuffer[0] = (offset >> 56) & 0xFF;
+        thisbuffer[1] = (offset >> 48) & 0xFF;
+        thisbuffer[2] = (offset >> 40) & 0xFF;
+        thisbuffer[3] = (offset >> 32) & 0xFF;
+        thisbuffer[4] = (offset >> 24) & 0xFF;
+        thisbuffer[5] = (offset >> 16) & 0xFF;
+        thisbuffer[6] = (offset >> 8) & 0xFF;
+        thisbuffer[7] = offset & 0xFF;
+        out.write(thisbuffer, 8);
+        delete[] thisbuffer;
+        delete[] mybuffer;
+        
+        //read index length
+               mybuffer = new char[4];
+        in.read(mybuffer,4);
+        offset = 0;
+        char* thisbuffer2 = new char[4];
+        thisbuffer2[0] = (offset >> 24) & 0xFF;
+        thisbuffer2[1] = (offset >> 16) & 0xFF;
+        thisbuffer2[2] = (offset >> 8) & 0xFF;
+        thisbuffer2[3] = offset & 0xFF;
+        out.write(thisbuffer2, 4);
+        delete[] thisbuffer2;
+        delete[] mybuffer;
+               
+        //change num reads
+        mybuffer = new char[4];
+        in.read(mybuffer,4);
+        delete[] mybuffer;
+        thisbuffer2 = new char[4];
+        if (endian == "BIG_ENDIAN") {
+            thisbuffer2[0] = (numTotalReads >> 24) & 0xFF;
+            thisbuffer2[1] = (numTotalReads >> 16) & 0xFF;
+            thisbuffer2[2] = (numTotalReads >> 8) & 0xFF;
+            thisbuffer2[3] = numTotalReads & 0xFF;
+        }else {
+            thisbuffer2[0] = numTotalReads & 0xFF;
+            thisbuffer2[1] = (numTotalReads >> 8) & 0xFF;
+            thisbuffer2[2] = (numTotalReads >> 16) & 0xFF;
+            thisbuffer2[3] = (numTotalReads >> 24) & 0xFF;
+        }
+        out.write(thisbuffer2, 4);
+        delete[] thisbuffer2;
+        
+        
+        //read header length
+        mybuffer = new char[2];
+        in.read(mybuffer,2);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //read key length
+        mybuffer = new char[2];
+        in.read(mybuffer,2);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //read number of flow reads
+        mybuffer = new char[2];
+        in.read(mybuffer,2);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //read format code
+        mybuffer = new char[1];
+        in.read(mybuffer,1);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //read flow chars
+        mybuffer = new char[commonHeaders[0].numFlowsPerRead];
+        in.read(mybuffer,commonHeaders[0].numFlowsPerRead);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        //read key
+        mybuffer = new char[commonHeaders[0].keyLength];
+        in.read(mybuffer,commonHeaders[0].keyLength);
+        out.write(mybuffer, in.gcount());
+        delete[] mybuffer;
+        
+        /* Pad to 8 chars */
+        unsigned long long spotInFile = in.tellg();
+        unsigned long long spot = (spotInFile + 7)& ~7;  // ~ inverts
+        in.seekg(spot);
+        
+        mybuffer = new char[spot-spotInFile];
+        out.write(mybuffer, spot-spotInFile);
+        delete[] mybuffer;
+        in.close();
+        out.close();
+        
+        m->appendBinaryFiles(outputFile, outputFileHeader);
+        m->renameFile(outputFileHeader, outputFile);
+        m->mothurRemove(outputFileHeader);
+        
+               return 0;
+        
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "adjustCommonHeader");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+bool MergeSfffilesCommand::readSeqData(ifstream& in, seqRead& read, int numFlowReads, Header& header, ofstream& out){
+       try {
+        unsigned long long startSpotInFile = in.tellg();
+               if (!in.eof()) {
+            
+            /*****************************************/
+            //read header
+            
+            //read header length
+                       char buffer [2];
+                       in.read(buffer, 2);
+                       header.headerLength = be_int2(*(unsigned short *)(&buffer));
+            
+                       //read name length
+                       char buffer2 [2];
+                       in.read(buffer2, 2);
+                       header.nameLength = be_int2(*(unsigned short *)(&buffer2));
+            
+                       //read num bases
+                       char buffer3 [4];
+                       in.read(buffer3, 4);
+                       header.numBases =  be_int4(*(unsigned int *)(&buffer3));
+            
+                       
+                       //read clip qual left
+                       char buffer4 [2];
+                       in.read(buffer4, 2);
+                       header.clipQualLeft =  be_int2(*(unsigned short *)(&buffer4));
+                       header.clipQualLeft = 5;
+            
+                       
+                       //read clip qual right
+                       char buffer5 [2];
+                       in.read(buffer5, 2);
+                       header.clipQualRight =  be_int2(*(unsigned short *)(&buffer5));
+            
+            
+                       //read clipAdapterLeft
+                       char buffer6 [2];
+                       in.read(buffer6, 2);
+                       header.clipAdapterLeft = be_int2(*(unsigned short *)(&buffer6));
+            
+            
+                       //read clipAdapterRight
+                       char buffer7 [2];
+                       in.read(buffer7, 2);
+                       header.clipAdapterRight = be_int2(*(unsigned short *)(&buffer7));
+            
+            
+                       //read name
+                       char* tempBuffer = new char[header.nameLength];
+                       in.read(&(*tempBuffer), header.nameLength);
+                       header.name = tempBuffer;
+                       if (header.name.length() > header.nameLength) { header.name = header.name.substr(0, header.nameLength);  }
+            
+                       delete[] tempBuffer;
+                                               
+                       /* Pad to 8 chars */
+                       unsigned long long spotInFile = in.tellg();
+                       unsigned long long spot = (spotInFile + 7)& ~7;
+                       in.seekg(spot);
+            
+            /*****************************************/
+            //sequence read
+            
+                       //read flowgram
+                       read.flowgram.resize(numFlowReads);
+                       for (int i = 0; i < numFlowReads; i++) {
+                               char buffer [2];
+                               in.read(buffer, 2);
+                               read.flowgram[i] = be_int2(*(unsigned short *)(&buffer));
+                       }
+            
+                       //read flowIndex
+                       read.flowIndex.resize(header.numBases);
+                       for (int i = 0; i < header.numBases; i++) {
+                               char temp[1];
+                               in.read(temp, 1);
+                               read.flowIndex[i] = be_int1(*(unsigned char *)(&temp));
+                       }
+            
+                       //read bases
+                       char* tempBuffer6 = new char[header.numBases];
+                       in.read(&(*tempBuffer6), header.numBases);
+                       read.bases = tempBuffer6;
+                       if (read.bases.length() > header.numBases) { read.bases = read.bases.substr(0, header.numBases);  }
+                       delete[] tempBuffer6;
+            
+                       //read qual scores
+                       read.qualScores.resize(header.numBases);
+                       for (int i = 0; i < header.numBases; i++) {
+                               char temp[1];
+                               in.read(temp, 1);
+                               read.qualScores[i] = be_int1(*(unsigned char *)(&temp));
+                       }
+            
+                       /* Pad to 8 chars */
+                       spotInFile = in.tellg();
+                       spot = (spotInFile + 7)& ~7;
+                       in.seekg(spot);
+            
+            char * mybuffer;
+            mybuffer = new char [spot-startSpotInFile];
+            
+            ifstream in2;
+            m->openInputFileBinary(currentFileName, in2);
+            in2.seekg(startSpotInFile);
+            in2.read(mybuffer,spot-startSpotInFile);
+            
+            out.write(mybuffer, in2.gcount());
+            numTotalReads++;
+            
+            delete[] mybuffer;
+            in2.close();
+            
+               }else{
+                       m->mothurOut("Error reading."); m->mothurOutEndLine();
+               }
+        
+        if (in.eof()) {  return true; }
+        
+               return false;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "readSeqData");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+bool MergeSfffilesCommand::sanityCheck(Header& header, seqRead& read) {
+       try {
+        bool okay = true;
+        string message = "[WARNING]: Your sff file may be corrupted! Sequence: " + header.name + "\n";
+        
+        if (header.clipQualLeft > read.bases.length()) {
+            okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
+        }
+        if (header.clipQualRight > read.bases.length()) {
+            okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.bases.length()) + " bases.\n";
+        }
+        if (header.clipQualLeft > read.qualScores.size()) {
+            okay = false; message += "Clip Qual Left = " + toString(header.clipQualLeft) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
+        }
+        if (header.clipQualRight > read.qualScores.size()) {
+            okay = false; message += "Clip Qual Right = " + toString(header.clipQualRight) + ", but we only read " + toString(read.qualScores.size()) + " quality scores.\n";
+        }
+        
+        if (okay == false) {
+            m->mothurOut(message); m->mothurOutEndLine();
+        }
+        
+               return okay;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "MergeSfffilesCommand", "sanityCheck");
+               exit(1);
+       }
+}
+//**********************************************************************************************************************
+int MergeSfffilesCommand::readFile(){
+       try {
+        
+        string filename;
+        
+        ifstream in;
+        m->openInputFile(file, in);
+        
+        while(!in.eof()) {
+            
+            if (m->control_pressed) { return 0; }
+            
+            in >> filename; m->gobble(in);
+            
+            if (m->debug) { m->mothurOut("[DEBUG]: filename = " + filename + ".\n"); }
+            
+            //check to make sure both are able to be opened
+            ifstream in2;
+            int openForward = m->openInputFile(filename, in2, "noerror");
+            
+            //if you can't open it, try default location
+            if (openForward == 1) {
+                if (m->getDefaultPath() != "") { //default path is set
+                    string tryPath = m->getDefaultPath() + m->getSimpleName(filename);
+                    m->mothurOut("Unable to open " + filename + ". Trying default " + tryPath); m->mothurOutEndLine();
+                    ifstream in3;
+                    openForward = m->openInputFile(tryPath, in3, "noerror");
+                    in3.close();
+                    filename = tryPath;
+                }
+            }
+            
+            //if you can't open it, try output location
+            if (openForward == 1) {
+                if (m->getOutputDir() != "") { //default path is set
+                    string tryPath = m->getOutputDir() + m->getSimpleName(filename);
+                    m->mothurOut("Unable to open " + filename + ". Trying output directory " + tryPath); m->mothurOutEndLine();
+                    ifstream in4;
+                    openForward = m->openInputFile(tryPath, in4, "noerror");
+                    filename = tryPath;
+                    in4.close();
+                }
+            }
+            
+            if (openForward == 1) { //can't find it
+                m->mothurOut("[WARNING]: can't find " + filename + ", ignoring.\n");
+            }else{  filenames.push_back(filename); }
+            
+        }
+        in.close();
+        
+        return 0;
+    }
+    catch(exception& e) {
+        m->errorOut(e, "MergeSfffilesCommand", "readFileNames");
+        exit(1);
+    }
+}
+//**********************************************************************************************************************
+
+
+
+