+//**********************************************************************************************************************
+int SffInfoCommand::parseSffTxt() {
+ try {
+
+ ifstream inSFF;
+ m->openInputFile(sfftxtFilename, inSFF);
+
+ if (outputDir == "") { outputDir += m->hasPath(sfftxtFilename); }
+
+ //output file names
+ ofstream outFasta, outQual, outFlow;
+ string outFastaFileName, outQualFileName;
+ string fileRoot = m->getRootName(m->getSimpleName(sfftxtFilename));
+ if (fileRoot.length() > 0) {
+ //rip off last .
+ fileRoot = fileRoot.substr(0, fileRoot.length()-1);
+ fileRoot = m->getRootName(fileRoot);
+ }
+
+ string outFlowFileName = outputDir + fileRoot + getOutputFileNameTag("flow");
+ if (trim) {
+ outFastaFileName = outputDir + fileRoot + getOutputFileNameTag("fasta");
+ outQualFileName = outputDir + fileRoot + getOutputFileNameTag("qfile");
+ }else{
+ outFastaFileName = outputDir + fileRoot + "raw." + getOutputFileNameTag("fasta");
+ outQualFileName = outputDir + fileRoot + "raw." + getOutputFileNameTag("qfile");
+ }
+
+ if (fasta) { m->openOutputFile(outFastaFileName, outFasta); outputNames.push_back(outFastaFileName); outputTypes["fasta"].push_back(outFastaFileName); }
+ if (qual) { m->openOutputFile(outQualFileName, outQual); outputNames.push_back(outQualFileName); outputTypes["qfile"].push_back(outQualFileName); }
+ 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); }
+
+ //read common header
+ string commonHeader = m->getline(inSFF);
+ string magicNumber = m->getline(inSFF);
+ string version = m->getline(inSFF);
+ string indexOffset = m->getline(inSFF);
+ string indexLength = m->getline(inSFF);
+ int numReads = parseHeaderLineToInt(inSFF);
+ string headerLength = m->getline(inSFF);
+ string keyLength = m->getline(inSFF);
+ int numFlows = parseHeaderLineToInt(inSFF);
+ string flowgramCode = m->getline(inSFF);
+ string flowChars = m->getline(inSFF);
+ string keySequence = m->getline(inSFF);
+ m->gobble(inSFF);
+
+ string seqName;
+
+ if (flow) { outFlow << numFlows << endl; }
+
+ for(int i=0;i<numReads;i++){
+
+ //sanity check
+ if (inSFF.eof()) { m->mothurOut("[ERROR]: Expected " + toString(numReads) + " but reached end of file at " + toString(i+1) + "."); m->mothurOutEndLine(); break; }
+
+ Header header;
+
+ //parse read header
+ inSFF >> seqName;
+ seqName = seqName.substr(1);
+ m->gobble(inSFF);
+ header.name = seqName;
+
+ string runPrefix = parseHeaderLineToString(inSFF); header.timestamp = runPrefix;
+ string regionNumber = parseHeaderLineToString(inSFF); header.region = regionNumber;
+ string xyLocation = parseHeaderLineToString(inSFF); header.xy = xyLocation;
+ m->gobble(inSFF);
+
+ string runName = parseHeaderLineToString(inSFF);
+ string analysisName = parseHeaderLineToString(inSFF);
+ string fullPath = parseHeaderLineToString(inSFF);
+ m->gobble(inSFF);
+
+ string readHeaderLen = parseHeaderLineToString(inSFF); convert(readHeaderLen, header.headerLength);
+ string nameLength = parseHeaderLineToString(inSFF); convert(nameLength, header.nameLength);
+ int numBases = parseHeaderLineToInt(inSFF); header.numBases = numBases;
+ string clipQualLeft = parseHeaderLineToString(inSFF); convert(clipQualLeft, header.clipQualLeft);
+ int clipQualRight = parseHeaderLineToInt(inSFF); header.clipQualRight = clipQualRight;
+ string clipAdapLeft = parseHeaderLineToString(inSFF); convert(clipAdapLeft, header.clipAdapterLeft);
+ string clipAdapRight = parseHeaderLineToString(inSFF); convert(clipAdapRight, header.clipAdapterRight);
+ m->gobble(inSFF);
+
+ seqRead read;
+
+ //parse read
+ vector<unsigned short> flowVector = parseHeaderLineToFloatVector(inSFF, numFlows); read.flowgram = flowVector;
+ vector<unsigned int> flowIndices = parseHeaderLineToIntVector(inSFF, numBases);
+
+ //adjust for print
+ vector<unsigned int> flowIndicesAdjusted; flowIndicesAdjusted.push_back(flowIndices[0]);
+ for (int j = 1; j < flowIndices.size(); j++) { flowIndicesAdjusted.push_back(flowIndices[j] - flowIndices[j-1]); }
+ read.flowIndex = flowIndicesAdjusted;
+
+ string bases = parseHeaderLineToString(inSFF); read.bases = bases;
+ vector<unsigned int> qualityScores = parseHeaderLineToIntVector(inSFF, numBases); read.qualScores = qualityScores;
+ m->gobble(inSFF);
+
+ //if you have provided an accosfile and this seq is not in it, then dont print
+ bool print = true;
+ if (seqNames.size() != 0) { if (seqNames.count(header.name) == 0) { print = false; } }
+
+ //print
+ if (print) {
+ if (fasta) { printFastaSeqData(outFasta, read, header); }
+ if (qual) { printQualSeqData(outQual, read, header); }
+ if (flow) { printFlowSeqData(outFlow, read, header); }
+ }
+
+ //report progress
+ if((i+1) % 10000 == 0){ m->mothurOut(toString(i+1)); m->mothurOutEndLine(); }
+
+ if (m->control_pressed) { break; }
+ }
+
+ //report progress
+ if (!m->control_pressed) { if((numReads) % 10000 != 0){ m->mothurOut(toString(numReads)); m->mothurOutEndLine(); } }
+
+ inSFF.close();
+
+ if (fasta) { outFasta.close(); }
+ if (qual) { outQual.close(); }
+ if (flow) { outFlow.close(); }
+
+ return 0;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "parseSffTxt");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+
+int SffInfoCommand::parseHeaderLineToInt(ifstream& file){
+ try {
+ int number;
+
+ while (!file.eof()) {
+
+ char c = file.get();
+ if (c == ':'){
+ file >> number;
+ break;
+ }
+
+ }
+ m->gobble(file);
+ return number;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "parseHeaderLineToInt");
+ exit(1);
+ }
+
+}
+
+//**********************************************************************************************************************
+
+string SffInfoCommand::parseHeaderLineToString(ifstream& file){
+ try {
+ string text;
+
+ while (!file.eof()) {
+ char c = file.get();
+
+ if (c == ':'){
+ //m->gobble(file);
+ //text = m->getline(file);
+ file >> text;
+ break;
+ }
+ }
+ m->gobble(file);
+
+ return text;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "parseHeaderLineToString");
+ exit(1);
+ }
+}
+
+//**********************************************************************************************************************
+
+vector<unsigned short> SffInfoCommand::parseHeaderLineToFloatVector(ifstream& file, int length){
+ try {
+ vector<unsigned short> floatVector(length);
+
+ while (!file.eof()) {
+ char c = file.get();
+ if (c == ':'){
+ float temp;
+ for(int i=0;i<length;i++){
+ file >> temp;
+ floatVector[i] = temp * 100;
+ }
+ break;
+ }
+ }
+ m->gobble(file);
+ return floatVector;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "parseHeaderLineToFloatVector");
+ exit(1);
+ }
+}
+
+//**********************************************************************************************************************
+
+vector<unsigned int> SffInfoCommand::parseHeaderLineToIntVector(ifstream& file, int length){
+ try {
+ vector<unsigned int> intVector(length);
+
+ while (!file.eof()) {
+ char c = file.get();
+ if (c == ':'){
+ for(int i=0;i<length;i++){
+ file >> intVector[i];
+ }
+ break;
+ }
+ }
+ m->gobble(file);
+ return intVector;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "parseHeaderLineToIntVector");
+ exit(1);
+ }
+}
+//***************************************************************************************************************
+
+bool SffInfoCommand::readOligos(string oligoFile){
+ try {
+ filehandles.clear();
+ numSplitReads.clear();
+ filehandlesHeaders.clear();
+
+ ifstream inOligos;
+ m->openInputFile(oligoFile, inOligos);
+
+ string type, oligo, group;
+
+ int indexPrimer = 0;
+ int indexBarcode = 0;
+
+ while(!inOligos.eof()){
+
+ inOligos >> type;
+
+ if(type[0] == '#'){
+ while (!inOligos.eof()) { char c = inOligos.get(); if (c == 10 || c == 13){ break; } } // get rest of line if there's any crap there
+ m->gobble(inOligos);
+ }
+ else{
+ m->gobble(inOligos);
+ //make type case insensitive
+ for(int i=0;i<type.length();i++){ type[i] = toupper(type[i]); }
+
+ inOligos >> oligo;
+
+ for(int i=0;i<oligo.length();i++){
+ oligo[i] = toupper(oligo[i]);
+ if(oligo[i] == 'U') { oligo[i] = 'T'; }
+ }
+
+ if(type == "FORWARD"){
+ group = "";
+
+ // get rest of line in case there is a primer name
+ while (!inOligos.eof()) {
+ char c = inOligos.get();
+ if (c == 10 || c == 13){ break; }
+ else if (c == 32 || c == 9){;} //space or tab
+ else { group += c; }
+ }
+
+ //check for repeat barcodes
+ map<string, int>::iterator itPrime = primers.find(oligo);
+ if (itPrime != primers.end()) { m->mothurOut("primer " + oligo + " is in your oligos file already."); m->mothurOutEndLine(); }
+
+ primers[oligo]=indexPrimer; indexPrimer++;
+ primerNameVector.push_back(group);
+ }else if(type == "REVERSE"){
+ //Sequence oligoRC("reverse", oligo);
+ //oligoRC.reverseComplement();
+ string oligoRC = reverseOligo(oligo);
+ revPrimer.push_back(oligoRC);
+ }
+ else if(type == "BARCODE"){
+ inOligos >> group;
+
+ //check for repeat barcodes
+ map<string, int>::iterator itBar = barcodes.find(oligo);
+ if (itBar != barcodes.end()) { m->mothurOut("barcode " + oligo + " is in your oligos file already."); m->mothurOutEndLine(); }
+
+ barcodes[oligo]=indexBarcode; indexBarcode++;
+ barcodeNameVector.push_back(group);
+ }else if(type == "LINKER"){
+ linker.push_back(oligo);
+ }else if(type == "SPACER"){
+ spacer.push_back(oligo);
+ }
+ else{ m->mothurOut("[WARNING]: " + type + " is not recognized as a valid type. Choices are forward, reverse, and barcode. Ignoring " + oligo + "."); m->mothurOutEndLine(); }
+ }
+ m->gobble(inOligos);
+ }
+ inOligos.close();
+
+ if(barcodeNameVector.size() == 0 && primerNameVector[0] == ""){ split = 1; }
+
+ //add in potential combos
+ if(barcodeNameVector.size() == 0){
+ barcodes[""] = 0;
+ barcodeNameVector.push_back("");
+ }
+
+ if(primerNameVector.size() == 0){
+ primers[""] = 0;
+ primerNameVector.push_back("");
+ }
+
+ filehandles.resize(barcodeNameVector.size());
+ for(int i=0;i<filehandles.size();i++){
+ filehandles[i].assign(primerNameVector.size(), "");
+ }
+
+ if(split > 1){
+ set<string> uniqueNames; //used to cleanup outputFileNames
+ for(map<string, int>::iterator itBar = barcodes.begin();itBar != barcodes.end();itBar++){
+ for(map<string, int>::iterator itPrimer = primers.begin();itPrimer != primers.end(); itPrimer++){
+
+ string primerName = primerNameVector[itPrimer->second];
+ string barcodeName = barcodeNameVector[itBar->second];
+
+ string comboGroupName = "";
+ string fastaFileName = "";
+ string qualFileName = "";
+ string nameFileName = "";
+
+ if(primerName == ""){
+ comboGroupName = barcodeNameVector[itBar->second];
+ }
+ else{
+ if(barcodeName == ""){
+ comboGroupName = primerNameVector[itPrimer->second];
+ }
+ else{
+ comboGroupName = barcodeNameVector[itBar->second] + "." + primerNameVector[itPrimer->second];
+ }
+ }
+
+ ofstream temp;
+ string thisFilename = outputDir + m->getRootName(m->getSimpleName(currentFileName)) + comboGroupName + "." + getOutputFileNameTag("sff");
+ if (uniqueNames.count(thisFilename) == 0) {
+ outputNames.push_back(thisFilename);
+ outputTypes["sff"].push_back(thisFilename);
+ uniqueNames.insert(thisFilename);
+ }
+
+ filehandles[itBar->second][itPrimer->second] = thisFilename;
+ m->openOutputFile(thisFilename, temp); temp.close();
+ }
+ }
+ }
+ numFPrimers = primers.size();
+ numLinkers = linker.size();
+ numSpacers = spacer.size();
+ noMatchFile = outputDir + m->getRootName(m->getSimpleName(currentFileName)) + "scrap." + getOutputFileNameTag("sff");
+ m->mothurRemove(noMatchFile);
+
+ bool allBlank = true;
+ for (int i = 0; i < barcodeNameVector.size(); i++) {
+ if (barcodeNameVector[i] != "") {
+ allBlank = false;
+ break;
+ }
+ }
+ for (int i = 0; i < primerNameVector.size(); i++) {
+ if (primerNameVector[i] != "") {
+ allBlank = false;
+ break;
+ }
+ }
+
+ filehandlesHeaders.resize(filehandles.size());
+ numSplitReads.resize(filehandles.size());
+ for (int i = 0; i < filehandles.size(); i++) {
+ numSplitReads[i].resize(filehandles[i].size(), 0);
+ for (int j = 0; j < filehandles[i].size(); j++) {
+ filehandlesHeaders[i].push_back(filehandles[i][j]+"headers");
+ }
+ }
+
+ if (allBlank) {
+ m->mothurOut("[WARNING]: your oligos file does not contain any group names. mothur will not create a split the sff file."); m->mothurOutEndLine();
+ split = 1;
+ return false;
+ }
+
+ return true;
+
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "readOligos");
+ exit(1);
+ }
+}
+//********************************************************************/
+string SffInfoCommand::reverseOligo(string oligo){
+ try {
+ string reverse = "";
+
+ for(int i=oligo.length()-1;i>=0;i--){
+
+ if(oligo[i] == 'A') { reverse += 'T'; }
+ else if(oligo[i] == 'T'){ reverse += 'A'; }
+ else if(oligo[i] == 'U'){ reverse += 'A'; }
+
+ else if(oligo[i] == 'G'){ reverse += 'C'; }
+ else if(oligo[i] == 'C'){ reverse += 'G'; }
+
+ else if(oligo[i] == 'R'){ reverse += 'Y'; }
+ else if(oligo[i] == 'Y'){ reverse += 'R'; }
+
+ else if(oligo[i] == 'M'){ reverse += 'K'; }
+ else if(oligo[i] == 'K'){ reverse += 'M'; }
+
+ else if(oligo[i] == 'W'){ reverse += 'W'; }
+ else if(oligo[i] == 'S'){ reverse += 'S'; }
+
+ else if(oligo[i] == 'B'){ reverse += 'V'; }
+ else if(oligo[i] == 'V'){ reverse += 'B'; }
+
+ else if(oligo[i] == 'D'){ reverse += 'H'; }
+ else if(oligo[i] == 'H'){ reverse += 'D'; }
+
+ else { reverse += 'N'; }
+ }
+
+
+ return reverse;
+ }
+ catch(exception& e) {
+ m->errorOut(e, "SffInfoCommand", "reverseOligo");
+ exit(1);
+ }
+}
+
+//**********************************************************************************************************************
+
+
+
+