]> git.donarmstrong.com Git - mothur.git/blob - sffinfocommand.cpp
added shhh.seqs command
[mothur.git] / sffinfocommand.cpp
1 /*
2  *  sffinfocommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 7/7/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "sffinfocommand.h"
11 #include "endiannessmacros.h"
12
13 //**********************************************************************************************************************
14 vector<string> SffInfoCommand::getValidParameters(){    
15         try {
16                 string Array[] =  {"sff","qfile","fasta","flow","trim","accnos","sfftxt","outputdir","inputdir", "outputdir"};
17                 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
18                 return myArray;
19         }
20         catch(exception& e) {
21                 m->errorOut(e, "SffInfoCommand", "getValidParameters");
22                 exit(1);
23         }
24 }
25 //**********************************************************************************************************************
26 SffInfoCommand::SffInfoCommand(){       
27         try {
28                 abort = true;
29                 //initialize outputTypes
30                 vector<string> tempOutNames;
31                 outputTypes["fasta"] = tempOutNames;
32                 outputTypes["flow"] = tempOutNames;
33                 outputTypes["sfftxt"] = tempOutNames;
34                 outputTypes["qual"] = tempOutNames;
35         }
36         catch(exception& e) {
37                 m->errorOut(e, "SffInfoCommand", "SffInfoCommand");
38                 exit(1);
39         }
40 }
41 //**********************************************************************************************************************
42 vector<string> SffInfoCommand::getRequiredParameters(){ 
43         try {
44                 string Array[] =  {"sff"};
45                 vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
46                 return myArray;
47         }
48         catch(exception& e) {
49                 m->errorOut(e, "SffInfoCommand", "getRequiredParameters");
50                 exit(1);
51         }
52 }
53 //**********************************************************************************************************************
54 vector<string> SffInfoCommand::getRequiredFiles(){      
55         try {
56                 vector<string> myArray;
57                 return myArray;
58         }
59         catch(exception& e) {
60                 m->errorOut(e, "SffInfoCommand", "getRequiredFiles");
61                 exit(1);
62         }
63 }
64 //**********************************************************************************************************************
65
66 SffInfoCommand::SffInfoCommand(string option)  {
67         try {
68                 abort = false;
69                 hasAccnos = false;
70                 
71                 //allow user to run help
72                 if(option == "help") { help(); abort = true; }
73                 
74                 else {
75                         //valid paramters for this command
76                         string Array[] =  {"sff","qfile","fasta","flow","trim","accnos","sfftxt","outputdir","inputdir", "outputdir"};
77                         vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
78                         
79                         OptionParser parser(option);
80                         map<string, string> parameters = parser.getParameters();
81                         
82                         ValidParameters validParameter;
83                         //check to make sure all parameters are valid for command
84                         for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) { 
85                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
86                         }
87                         
88                         //initialize outputTypes
89                         vector<string> tempOutNames;
90                         outputTypes["fasta"] = tempOutNames;
91                         outputTypes["flow"] = tempOutNames;
92                         outputTypes["sfftxt"] = tempOutNames;
93                         outputTypes["qual"] = tempOutNames;
94                         
95                         //if the user changes the output directory command factory will send this info to us in the output parameter 
96                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = "";         }
97                         
98                         //if the user changes the input directory command factory will send this info to us in the output parameter 
99                         string inputDir = validParameter.validFile(parameters, "inputdir", false);        if (inputDir == "not found"){ inputDir = "";          }
100
101                         sffFilename = validParameter.validFile(parameters, "sff", false);
102                         if (sffFilename == "not found") { m->mothurOut("sff is a required parameter for the sffinfo command."); m->mothurOutEndLine(); abort = true;  }
103                         else { 
104                                 m->splitAtDash(sffFilename, filenames);
105                                 
106                                 //go through files and make sure they are good, if not, then disregard them
107                                 for (int i = 0; i < filenames.size(); i++) {
108                                         if (inputDir != "") {
109                                                 string path = m->hasPath(filenames[i]);
110                                                 //if the user has not given a path then, add inputdir. else leave path alone.
111                                                 if (path == "") {       filenames[i] = inputDir + filenames[i];         }
112                                         }
113         
114                                         ifstream in;
115                                         int ableToOpen = m->openInputFile(filenames[i], in, "noerror");
116                                 
117                                         //if you can't open it, try default location
118                                         if (ableToOpen == 1) {
119                                                 if (m->getDefaultPath() != "") { //default path is set
120                                                         string tryPath = m->getDefaultPath() + m->getSimpleName(filenames[i]);
121                                                         m->mothurOut("Unable to open " + filenames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
122                                                         ifstream in2;
123                                                         ableToOpen = m->openInputFile(tryPath, in2, "noerror");
124                                                         in2.close();
125                                                         filenames[i] = tryPath;
126                                                 }
127                                         }
128                                         
129                                         //if you can't open it, try default location
130                                         if (ableToOpen == 1) {
131                                                 if (m->getOutputDir() != "") { //default path is set
132                                                         string tryPath = m->getOutputDir() + m->getSimpleName(filenames[i]);
133                                                         m->mothurOut("Unable to open " + filenames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
134                                                         ifstream in2;
135                                                         ableToOpen = m->openInputFile(tryPath, in2, "noerror");
136                                                         in2.close();
137                                                         filenames[i] = tryPath;
138                                                 }
139                                         }
140                                         
141                                         in.close();
142                                         
143                                         if (ableToOpen == 1) { 
144                                                 m->mothurOut("Unable to open " + filenames[i] + ". It will be disregarded."); m->mothurOutEndLine();
145                                                 //erase from file list
146                                                 filenames.erase(filenames.begin()+i);
147                                                 i--;
148                                         }
149                                 }
150                                 
151                                 //make sure there is at least one valid file left
152                                 if (filenames.size() == 0) { m->mothurOut("no valid files."); m->mothurOutEndLine(); abort = true; }
153                         }
154                         
155                         accnosName = validParameter.validFile(parameters, "accnos", false);
156                         if (accnosName == "not found") { accnosName = "";  }
157                         else { 
158                                 hasAccnos = true;
159                                 m->splitAtDash(accnosName, accnosFileNames);
160                                 
161                                 //go through files and make sure they are good, if not, then disregard them
162                                 for (int i = 0; i < accnosFileNames.size(); i++) {
163                                         if (inputDir != "") {
164                                                 string path = m->hasPath(accnosFileNames[i]);
165                                                 //if the user has not given a path then, add inputdir. else leave path alone.
166                                                 if (path == "") {       accnosFileNames[i] = inputDir + accnosFileNames[i];             }
167                                         }
168         
169                                         ifstream in;
170                                         int ableToOpen = m->openInputFile(accnosFileNames[i], in, "noerror");
171                                 
172                                         //if you can't open it, try default location
173                                         if (ableToOpen == 1) {
174                                                 if (m->getDefaultPath() != "") { //default path is set
175                                                         string tryPath = m->getDefaultPath() + m->getSimpleName(accnosFileNames[i]);
176                                                         m->mothurOut("Unable to open " + accnosFileNames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
177                                                         ifstream in2;
178                                                         ableToOpen = m->openInputFile(tryPath, in2, "noerror");
179                                                         in2.close();
180                                                         accnosFileNames[i] = tryPath;
181                                                 }
182                                         }
183                                         //if you can't open it, try default location
184                                         if (ableToOpen == 1) {
185                                                 if (m->getOutputDir() != "") { //default path is set
186                                                         string tryPath = m->getOutputDir() + m->getSimpleName(accnosFileNames[i]);
187                                                         m->mothurOut("Unable to open " + accnosFileNames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
188                                                         ifstream in2;
189                                                         ableToOpen = m->openInputFile(tryPath, in2, "noerror");
190                                                         in2.close();
191                                                         accnosFileNames[i] = tryPath;
192                                                 }
193                                         }
194                                         in.close();
195                                         
196                                         if (ableToOpen == 1) { 
197                                                 m->mothurOut("Unable to open " + accnosFileNames[i] + ". It will be disregarded."); m->mothurOutEndLine();
198                                                 //erase from file list
199                                                 accnosFileNames.erase(accnosFileNames.begin()+i);
200                                                 i--;
201                                         }
202                                 }
203                                 
204                                 //make sure there is at least one valid file left
205                                 if (accnosFileNames.size() == 0) { m->mothurOut("no valid files."); m->mothurOutEndLine(); abort = true; }
206                         }
207                         
208                         if (hasAccnos) {
209                                 if (accnosFileNames.size() != filenames.size()) { abort = true; m->mothurOut("If you provide a accnos file, you must have one for each sff file."); m->mothurOutEndLine(); }
210                         }
211                         
212                         string temp = validParameter.validFile(parameters, "qfile", false);                     if (temp == "not found"){       temp = "T";                             }
213                         qual = m->isTrue(temp); 
214                         
215                         temp = validParameter.validFile(parameters, "fasta", false);                            if (temp == "not found"){       temp = "T";                             }
216                         fasta = m->isTrue(temp); 
217                         
218                         temp = validParameter.validFile(parameters, "flow", false);                                     if (temp == "not found"){       temp = "F";                             }
219                         flow = m->isTrue(temp); 
220                         
221                         temp = validParameter.validFile(parameters, "trim", false);                                     if (temp == "not found"){       temp = "T";                             }
222                         trim = m->isTrue(temp); 
223                         
224                         temp = validParameter.validFile(parameters, "sfftxt", false);                           if (temp == "not found"){       temp = "F";                             }
225                         sfftxt = m->isTrue(temp); 
226                 }
227         }
228         catch(exception& e) {
229                 m->errorOut(e, "SffInfoCommand", "SffInfoCommand");
230                 exit(1);
231         }
232 }
233 //**********************************************************************************************************************
234
235 void SffInfoCommand::help(){
236         try {
237                 m->mothurOut("The sffinfo command reads a sff file and extracts the sequence data.\n");
238                 m->mothurOut("The sffinfo command parameters are sff, fasta, qfile, accnos, flow, sfftxt, and trim. sff is required. \n");
239                 m->mothurOut("The sff parameter allows you to enter the sff file you would like to extract data from.  You may enter multiple files by separating them by -'s.\n");
240                 m->mothurOut("The fasta parameter allows you to indicate if you would like a fasta formatted file generated.  Default=True. \n");
241                 m->mothurOut("The qfile parameter allows you to indicate if you would like a quality file generated.  Default=True. \n");
242                 m->mothurOut("The flow parameter allows you to indicate if you would like a flowgram file generated.  Default=False. \n");
243                 m->mothurOut("The sfftxt parameter allows you to indicate if you would like a sff.txt file generated.  Default=False. \n");
244                 m->mothurOut("The trim parameter allows you to indicate if you would like a sequences and quality scores trimmed to the clipQualLeft and clipQualRight values.  Default=True. \n");
245                 m->mothurOut("The accnos parameter allows you to provide a accnos file containing the names of the sequences you would like extracted. You may enter multiple files by separating them by -'s. \n");
246                 m->mothurOut("Example sffinfo(sff=mySffFile.sff, trim=F).\n");
247                 m->mothurOut("Note: No spaces between parameter labels (i.e. sff), '=' and parameters (i.e.yourSffFileName).\n\n");
248         }
249         catch(exception& e) {
250                 m->errorOut(e, "SffInfoCommand", "help");
251                 exit(1);
252         }
253 }
254 //**********************************************************************************************************************
255
256 SffInfoCommand::~SffInfoCommand(){}
257
258 //**********************************************************************************************************************
259 int SffInfoCommand::execute(){
260         try {
261                 
262                 if (abort == true) { return 0; }
263                 
264                 for (int s = 0; s < filenames.size(); s++) {
265                         
266                         if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       remove(outputNames[i].c_str());         } return 0; }
267                         
268                         int start = time(NULL);
269                         
270                         m->mothurOut("Extracting info from " + filenames[s] + " ..." ); m->mothurOutEndLine();
271                         
272                         string accnos = "";
273                         if (hasAccnos) { accnos = accnosFileNames[s]; }
274                         
275                         int numReads = extractSffInfo(filenames[s], accnos);
276
277                         m->mothurOut("It took " + toString(time(NULL) - start) + " secs to extract " + toString(numReads) + ".");
278                 }
279                 
280                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       remove(outputNames[i].c_str());         } return 0; }
281                 
282                 //report output filenames
283                 m->mothurOutEndLine();
284                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
285                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
286                 m->mothurOutEndLine();
287
288                 return 0;
289         }
290         catch(exception& e) {
291                 m->errorOut(e, "SffInfoCommand", "execute");
292                 exit(1);
293         }
294 }
295 //**********************************************************************************************************************
296 int SffInfoCommand::extractSffInfo(string input, string accnos){
297         try {
298                 
299                 if (outputDir == "") {  outputDir += m->hasPath(input); }
300                 
301                 if (accnos != "")       {  readAccnosFile(accnos);  }
302                 else                            {       seqNames.clear();               }
303
304                 ofstream outSfftxt, outFasta, outQual, outFlow;
305                 string outFastaFileName, outQualFileName;
306                 string sfftxtFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "sff.txt";
307                 string outFlowFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "flow";
308                 if (trim) {
309                         outFastaFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "fasta";
310                         outQualFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "qual";
311                 }else{
312                         outFastaFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "raw.fasta";
313                         outQualFileName = outputDir + m->getRootName(m->getSimpleName(input)) + "raw.qual";
314                 }
315                 
316                 if (sfftxt) { m->openOutputFile(sfftxtFileName, outSfftxt); outSfftxt.setf(ios::fixed, ios::floatfield); outSfftxt.setf(ios::showpoint);  outputNames.push_back(sfftxtFileName);  outputTypes["sfftxt"].push_back(sfftxtFileName); }
317                 if (fasta)      { m->openOutputFile(outFastaFileName, outFasta);        outputNames.push_back(outFastaFileName); outputTypes["fasta"].push_back(outFastaFileName); }
318                 if (qual)       { m->openOutputFile(outQualFileName, outQual);          outputNames.push_back(outQualFileName); outputTypes["qual"].push_back(outQualFileName);  }
319                 if (flow)       { m->openOutputFile(outFlowFileName, outFlow);          outputNames.push_back(outFlowFileName);  outFlow.setf(ios::fixed, ios::floatfield); outFlow.setf(ios::showpoint); outputTypes["flow"].push_back(outFlowFileName);  }
320                 
321                 ifstream in;
322                 in.open(input.c_str(), ios::binary);
323                 
324                 CommonHeader header; 
325                 readCommonHeader(in, header);
326                 
327                 int count = 0;
328                 
329                 //check magic number and version
330                 if (header.magicNumber != 779314790) { m->mothurOut("Magic Number is not correct, not a valid .sff file"); m->mothurOutEndLine(); return count; }
331                 if (header.version != "0001") { m->mothurOut("Version is not supported, only support version 0001."); m->mothurOutEndLine(); return count; }
332         
333                 //print common header
334                 if (sfftxt) {   printCommonHeader(outSfftxt, header);           }
335                 if (flow)       {       outFlow << header.numFlowsPerRead << endl;      }
336                         
337                 //read through the sff file
338                 while (!in.eof()) {
339                         
340                         bool print = true;
341                         
342                         //read header
343                         Header readheader;
344                         readHeader(in, readheader);
345                         
346                         //read data
347                         seqRead read; 
348                         readSeqData(in, read, header.numFlowsPerRead, readheader.numBases);
349                                 
350                         //if you have provided an accosfile and this seq is not in it, then dont print
351                         if (seqNames.size() != 0) {   if (seqNames.count(readheader.name) == 0) { print = false; }  }
352                         
353                         //print 
354                         if (print) {
355                                 if (sfftxt) { printHeader(outSfftxt, readheader); printSffTxtSeqData(outSfftxt, read, readheader); }
356                                 if (fasta)      {       printFastaSeqData(outFasta, read, readheader);  }
357                                 if (qual)       {       printQualSeqData(outQual, read, readheader);    }
358                                 if (flow)       {       printFlowSeqData(outFlow, read, readheader);    }
359                         }
360                         
361                         count++;
362                 
363                         //report progress
364                         if((count+1) % 10000 == 0){     m->mothurOut(toString(count+1)); m->mothurOutEndLine();         }
365                 
366                         if (m->control_pressed) { count = 0; break;   }
367                         
368                         if (count >= header.numReads) { break; }
369                 }
370                 
371                 //report progress
372                 if (!m->control_pressed) {   if((count) % 10000 != 0){  m->mothurOut(toString(count)); m->mothurOutEndLine();           }  }
373                 
374                 in.close();
375                 
376                 if (sfftxt) {  outSfftxt.close();       }
377                 if (fasta)      {  outFasta.close();    }
378                 if (qual)       {  outQual.close();             }
379                 if (flow)       {  outFlow.close();             }
380                 
381                 return count;
382         }
383         catch(exception& e) {
384                 m->errorOut(e, "SffInfoCommand", "extractSffInfo");
385                 exit(1);
386         }
387 }
388 //**********************************************************************************************************************
389 int SffInfoCommand::readCommonHeader(ifstream& in, CommonHeader& header){
390         try {
391
392                 if (!in.eof()) {
393
394                         //read magic number
395                         char buffer[4];
396                         in.read(buffer, 4);
397                         header.magicNumber = be_int4(*(unsigned int *)(&buffer));
398                 
399                         //read version
400                         char buffer9[4];
401                         in.read(buffer9, 4);
402                         header.version = "";
403                         for (int i = 0; i < 4; i++) {  header.version += toString((int)(buffer9[i])); }
404                                 
405                         //read offset
406                         char buffer2 [8];
407                         in.read(buffer2, 8);
408                         header.indexOffset =  be_int8(*(unsigned long int *)(&buffer2));
409                         
410                         //read index length
411                         char buffer3 [4];
412                         in.read(buffer3, 4);
413                         header.indexLength =  be_int4(*(unsigned int *)(&buffer3));
414                         
415                         //read num reads
416                         char buffer4 [4];
417                         in.read(buffer4, 4);
418                         header.numReads =  be_int4(*(unsigned int *)(&buffer4));
419                                 
420                         //read header length
421                         char buffer5 [2];
422                         in.read(buffer5, 2);
423                         header.headerLength =  be_int2(*(unsigned short *)(&buffer5));
424                                         
425                         //read key length
426                         char buffer6 [2];
427                         in.read(buffer6, 2);
428                         header.keyLength = be_int2(*(unsigned short *)(&buffer6));
429                         
430                         //read number of flow reads
431                         char buffer7 [2];
432                         in.read(buffer7, 2);
433                         header.numFlowsPerRead =  be_int2(*(unsigned short *)(&buffer7));
434                                 
435                         //read format code
436                         char buffer8 [1];
437                         in.read(buffer8, 1);
438                         header.flogramFormatCode = (int)(buffer8[0]);
439                         
440                         //read flow chars
441                         char* tempBuffer = new char[header.numFlowsPerRead];
442                         in.read(&(*tempBuffer), header.numFlowsPerRead); 
443                         header.flowChars = tempBuffer;
444                         if (header.flowChars.length() > header.numFlowsPerRead) { header.flowChars = header.flowChars.substr(0, header.numFlowsPerRead);  }
445                         delete[] tempBuffer;
446                         
447                         //read key
448                         char* tempBuffer2 = new char[header.keyLength];
449                         in.read(&(*tempBuffer2), header.keyLength);
450                         header.keySequence = tempBuffer2;
451                         if (header.keySequence.length() > header.keyLength) { header.keySequence = header.keySequence.substr(0, header.keyLength);  }
452                         delete[] tempBuffer2;
453                                 
454                         /* Pad to 8 chars */
455                         unsigned long int spotInFile = in.tellg();
456                         unsigned long int spot = (spotInFile + 7)& ~7;  // ~ inverts
457                         in.seekg(spot);
458                         
459                 }else{
460                         m->mothurOut("Error reading sff common header."); m->mothurOutEndLine();
461                 }
462
463                 return 0;
464         }
465         catch(exception& e) {
466                 m->errorOut(e, "SffInfoCommand", "readCommonHeader");
467                 exit(1);
468         }
469 }
470 //**********************************************************************************************************************
471 int SffInfoCommand::readHeader(ifstream& in, Header& header){
472         try {
473         
474                 if (!in.eof()) {
475                         
476                         //read header length
477                         char buffer [2];
478                         in.read(buffer, 2);
479                         header.headerLength = be_int2(*(unsigned short *)(&buffer));
480                                                 
481                         //read name length
482                         char buffer2 [2];
483                         in.read(buffer2, 2);
484                         header.nameLength = be_int2(*(unsigned short *)(&buffer2));
485
486                         //read num bases
487                         char buffer3 [4];
488                         in.read(buffer3, 4);
489                         header.numBases =  be_int4(*(unsigned int *)(&buffer3));
490                         
491                         //read clip qual left
492                         char buffer4 [2];
493                         in.read(buffer4, 2);
494                         header.clipQualLeft =  be_int2(*(unsigned short *)(&buffer4));
495                         header.clipQualLeft = 5; 
496                         
497                         //read clip qual right
498                         char buffer5 [2];
499                         in.read(buffer5, 2);
500                         header.clipQualRight =  be_int2(*(unsigned short *)(&buffer5));
501                         
502                         //read clipAdapterLeft
503                         char buffer6 [2];
504                         in.read(buffer6, 2);
505                         header.clipAdapterLeft = be_int2(*(unsigned short *)(&buffer6));
506
507                         //read clipAdapterRight
508                         char buffer7 [2];
509                         in.read(buffer7, 2);
510                         header.clipAdapterRight = be_int2(*(unsigned short *)(&buffer7));
511                 
512                         //read name
513                         char* tempBuffer = new char[header.nameLength];
514                         in.read(&(*tempBuffer), header.nameLength);
515                         header.name = tempBuffer;
516                         if (header.name.length() > header.nameLength) { header.name = header.name.substr(0, header.nameLength);  }
517                         delete[] tempBuffer;
518                         
519                         //extract info from name
520                         decodeName(header.timestamp, header.region, header.xy, header.name);
521                         
522                         /* Pad to 8 chars */
523                         unsigned long int spotInFile = in.tellg();
524                         unsigned long int spot = (spotInFile + 7)& ~7;
525                         in.seekg(spot);
526                         
527                 }else{
528                         m->mothurOut("Error reading sff header info."); m->mothurOutEndLine();
529                 }
530
531                 return 0;
532         }
533         catch(exception& e) {
534                 m->errorOut(e, "SffInfoCommand", "readHeader");
535                 exit(1);
536         }
537 }
538 //**********************************************************************************************************************
539 int SffInfoCommand::readSeqData(ifstream& in, seqRead& read, int numFlowReads, int numBases){
540         try {
541         
542                 if (!in.eof()) {
543         
544                         //read flowgram
545                         read.flowgram.resize(numFlowReads);
546                         for (int i = 0; i < numFlowReads; i++) {  
547                                 char buffer [2];
548                                 in.read(buffer, 2);
549                                 read.flowgram[i] = be_int2(*(unsigned short *)(&buffer));
550                         }
551         
552                         //read flowIndex
553                         read.flowIndex.resize(numBases);
554                         for (int i = 0; i < numBases; i++) {  
555                                 char temp[1];
556                                 in.read(temp, 1);
557                                 read.flowIndex[i] = be_int1(*(unsigned char *)(&temp));
558                         }
559         
560                         //read bases
561                         char* tempBuffer = new char[numBases];
562                         in.read(&(*tempBuffer), numBases);
563                         read.bases = tempBuffer;
564                         if (read.bases.length() > numBases) { read.bases = read.bases.substr(0, numBases);  }
565                         delete[] tempBuffer;
566
567                         //read qual scores
568                         read.qualScores.resize(numBases);
569                         for (int i = 0; i < numBases; i++) {  
570                                 char temp[1];
571                                 in.read(temp, 1);
572                                 read.qualScores[i] = be_int1(*(unsigned char *)(&temp));
573                         }
574         
575                         /* Pad to 8 chars */
576                         unsigned long int spotInFile = in.tellg();
577                         unsigned long int spot = (spotInFile + 7)& ~7;
578                         in.seekg(spot);
579                         
580                 }else{
581                         m->mothurOut("Error reading."); m->mothurOutEndLine();
582                 }
583
584                 return 0;
585         }
586         catch(exception& e) {
587                 m->errorOut(e, "SffInfoCommand", "readSeqData");
588                 exit(1);
589         }
590 }
591 //**********************************************************************************************************************
592 int SffInfoCommand::decodeName(string& timestamp, string& region, string& xy, string name) {
593         try {
594                 
595                 string time = name.substr(0, 6);
596                 unsigned int timeNum = m->fromBase36(time);
597                         
598                 int q1 = timeNum / 60;
599                 int sec = timeNum - 60 * q1;
600                 int q2 = q1 / 60;
601                 int minute = q1 - 60 * q2;
602                 int q3 = q2 / 24;
603                 int hr = q2 - 24 * q3;
604                 int q4 = q3 / 32;
605                 int day = q3 - 32 * q4;
606                 int q5 = q4 / 13;
607                 int mon = q4 - 13 * q5;
608                 int year = 2000 + q5;
609                 
610                 timestamp = toString(year) + "_" + toString(mon) + "_" + toString(day) + "_" + toString(hr) + "_" + toString(minute) + "_" + toString(sec);
611                 
612                 region = name.substr(7, 2);
613                 
614                 string xyNum = name.substr(9);
615                 unsigned int myXy = m->fromBase36(xyNum);
616                 int x = myXy >> 12;
617                 int y = myXy & 4095;
618                 
619                 xy = toString(x) + "_" + toString(y);
620                         
621                 return 0;
622         }
623         catch(exception& e) {
624                 m->errorOut(e, "SffInfoCommand", "decodeName");
625                 exit(1);
626         }
627 }
628 //**********************************************************************************************************************
629 int SffInfoCommand::printCommonHeader(ofstream& out, CommonHeader& header) {
630         try {
631         
632                 out << "Common Header:\nMagic Number: " << header.magicNumber << endl;
633                 out << "Version: " << header.version << endl;
634                 out << "Index Offset: " << header.indexOffset << endl;
635                 out << "Index Length: " << header.indexLength << endl;
636                 out << "Number of Reads: " << header.numReads << endl;
637                 out << "Header Length: " << header.headerLength << endl;
638                 out << "Key Length: " << header.keyLength << endl;
639                 out << "Number of Flows: " << header.numFlowsPerRead << endl;
640                 out << "Format Code: " << header.flogramFormatCode << endl;
641                 out << "Flow Chars: " << header.flowChars << endl;
642                 out << "Key Sequence: " << header.keySequence << endl << endl;
643                         
644                 return 0;
645         }
646         catch(exception& e) {
647                 m->errorOut(e, "SffInfoCommand", "printCommonHeader");
648                 exit(1);
649         }
650 }
651 //**********************************************************************************************************************
652 int SffInfoCommand::printHeader(ofstream& out, Header& header) {
653         try {
654                 
655                 out << ">" << header.name << endl;
656                 out << "Run Prefix: " << header.timestamp << endl;
657                 out << "Region #:  " << header.region << endl;
658                 out << "XY Location: " << header.xy << endl << endl;
659                 
660                 out << "Run Name:  " << endl;
661                 out << "Analysis Name:  " << endl;
662                 out << "Full Path: " << endl << endl;
663                 
664                 out << "Read Header Len: " << header.headerLength << endl;
665                 out << "Name Length: " << header.nameLength << endl;
666                 out << "# of Bases: " << header.numBases << endl;
667                 out << "Clip Qual Left: " << header.clipQualLeft << endl;
668                 out << "Clip Qual Right: " << header.clipQualRight << endl;
669                 out << "Clip Adap Left: " << header.clipAdapterLeft << endl;
670                 out << "Clip Adap Right: " << header.clipAdapterRight << endl << endl;
671                 
672                 return 0;
673         }
674         catch(exception& e) {
675                 m->errorOut(e, "SffInfoCommand", "printHeader");
676                 exit(1);
677         }
678 }
679
680 //**********************************************************************************************************************
681 int SffInfoCommand::printSffTxtSeqData(ofstream& out, seqRead& read, Header& header) {
682         try {
683                 
684                 out << "Flowgram: ";
685                 for (int i = 0; i < read.flowgram.size(); i++) { out << setprecision(2) << (read.flowgram[i]/(float)100) << '\t';  }
686                 
687                 out << endl <<  "Flow Indexes: ";
688                 int sum = 0;
689                 for (int i = 0; i < read.flowIndex.size(); i++) {  sum +=  read.flowIndex[i];  out << sum << '\t'; }
690                 
691                 //make the bases you want to clip lowercase and the bases you want to keep upper case
692                 if(header.clipQualRight == 0){  header.clipQualRight = read.bases.length();     }
693                 for (int i = 0; i < (header.clipQualLeft-1); i++) { read.bases[i] = tolower(read.bases[i]); }
694                 for (int i = (header.clipQualLeft-1); i < (header.clipQualRight-1); i++) {   read.bases[i] = toupper(read.bases[i]);  }
695                 for (int i = (header.clipQualRight-1); i < read.bases.length(); i++) {   read.bases[i] = tolower(read.bases[i]);  }
696                 
697                 out << endl <<  "Bases: " << read.bases << endl << "Quality Scores: ";
698                 for (int i = 0; i < read.qualScores.size(); i++) {   out << read.qualScores[i] << '\t';  }
699         
700                 
701                 out << endl << endl;
702                 
703                 return 0;
704         }
705         catch(exception& e) {
706                 m->errorOut(e, "SffInfoCommand", "printSffTxtSeqData");
707                 exit(1);
708         }
709 }
710 //**********************************************************************************************************************
711 int SffInfoCommand::printFastaSeqData(ofstream& out, seqRead& read, Header& header) {
712         try {
713                 
714                 string seq = read.bases;
715                 
716                 if (trim) {
717                         if(header.clipQualRight < header.clipQualLeft){
718                                 seq = "NNNN";
719                         }
720                         else if((header.clipQualRight != 0) && ((header.clipQualRight-header.clipQualLeft) >= 0)){
721                                 seq = seq.substr((header.clipQualLeft-1), (header.clipQualRight-header.clipQualLeft));
722                         }
723                         else {
724                                 seq = seq.substr(header.clipQualLeft-1);
725                         }
726                 }else{
727                         //if you wanted the sfftxt then you already converted the bases to the right case
728                         if (!sfftxt) {
729                                 //make the bases you want to clip lowercase and the bases you want to keep upper case
730                                 if(header.clipQualRight == 0){  header.clipQualRight = seq.length();    }
731                                 for (int i = 0; i < (header.clipQualLeft-1); i++) { seq[i] = tolower(seq[i]);  }
732                                 for (int i = (header.clipQualLeft-1); i < (header.clipQualRight-1); i++)  {   seq[i] = toupper(seq[i]);  }
733                                 for (int i = (header.clipQualRight-1); i < seq.length(); i++) {   seq[i] = tolower(seq[i]);  }
734                         }
735                 }
736                 
737                 out << ">" << header.name  << " xy=" << header.xy << endl;
738                 out << seq << endl;
739                 
740                 return 0;
741         }
742         catch(exception& e) {
743                 m->errorOut(e, "SffInfoCommand", "printFastaSeqData");
744                 exit(1);
745         }
746 }
747
748 //**********************************************************************************************************************
749 int SffInfoCommand::printQualSeqData(ofstream& out, seqRead& read, Header& header) {
750         try {
751                 
752                 if (trim) {
753                         if(header.clipQualRight < header.clipQualLeft){
754                                 out << "0\t0\t0\t0";
755                         }
756                         else if((header.clipQualRight != 0) && ((header.clipQualRight-header.clipQualLeft) >= 0)){
757                                 out << ">" << header.name << " xy=" << header.xy << " length=" << (header.clipQualRight-header.clipQualLeft) << endl;
758                                 for (int i = (header.clipQualLeft-1); i < (header.clipQualRight-1); i++) {   out << read.qualScores[i] << '\t'; }
759                         }
760                         else{
761                                 out << ">" << header.name << " xy=" << header.xy << " length=" << (header.clipQualRight-header.clipQualLeft) << endl;
762                                 for (int i = (header.clipQualLeft-1); i < read.qualScores.size(); i++) {   out << read.qualScores[i] << '\t';   }                       
763                         }
764                 }else{
765                         out << ">" << header.name << " xy=" << header.xy << " length=" << read.qualScores.size() << endl;
766                         for (int i = 0; i < read.qualScores.size(); i++) {   out << read.qualScores[i] << '\t';  }
767                 }
768                 
769                 out << endl;
770                 
771                 return 0;
772         }
773         catch(exception& e) {
774                 m->errorOut(e, "SffInfoCommand", "printQualSeqData");
775                 exit(1);
776         }
777 }
778
779 //**********************************************************************************************************************
780 int SffInfoCommand::printFlowSeqData(ofstream& out, seqRead& read, Header& header) {
781         try {
782                 if(header.clipQualRight > header.clipQualLeft){
783                         
784                         int rightIndex = 0;
785                         for (int i = 0; i < header.clipQualRight; i++) {  rightIndex +=  read.flowIndex[i];     }
786
787                         out << header.name << ' ' << rightIndex;
788                         for (int i = 0; i < read.flowgram.size(); i++) { out << setprecision(2) << ' ' << (read.flowgram[i]/(float)100);  }
789                         out << endl;
790                 }
791                 
792                 
793                 return 0;
794         }
795         catch(exception& e) {
796                 m->errorOut(e, "SffInfoCommand", "printFlowSeqData");
797                 exit(1);
798         }
799 }
800 //**********************************************************************************************************************
801 int SffInfoCommand::readAccnosFile(string filename) {
802         try {
803                 //remove old names
804                 seqNames.clear();
805                 
806                 ifstream in;
807                 m->openInputFile(filename, in);
808                 string name;
809                 
810                 while(!in.eof()){
811                         in >> name; m->gobble(in);
812                                                 
813                         seqNames.insert(name);
814                         
815                         if (m->control_pressed) { seqNames.clear(); break; }
816                 }
817                 in.close();             
818                 
819                 return 0;
820         }
821         catch(exception& e) {
822                 m->errorOut(e, "SffInfoCommand", "readAccnosFile");
823                 exit(1);
824         }
825 }
826 //**********************************************************************************************************************/