]> git.donarmstrong.com Git - mothur.git/blobdiff - subsamplecommand.cpp
added load.logfile command. changed summary.single output for subsample=t.
[mothur.git] / subsamplecommand.cpp
index e365441d69bfeebc826bff13f3be4728ae54a264..35441013919fbfe55452532e735b5bd1d7673f2f 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "subsamplecommand.h"
 #include "sharedutilities.h"
+#include "deconvolutecommand.h"
+#include "subsample.h"
 
 //**********************************************************************************************************************
 vector<string> SubSampleCommand::setParameters(){      
@@ -61,6 +63,33 @@ string SubSampleCommand::getHelpString(){
                exit(1);
        }
 }
+//**********************************************************************************************************************
+string SubSampleCommand::getOutputFileNameTag(string type, string inputName=""){       
+       try {
+        string outputFileName = "";
+               map<string, vector<string> >::iterator it;
+        
+        //is this a type this command creates
+        it = outputTypes.find(type);
+        if (it == outputTypes.end()) {  m->mothurOut("[ERROR]: this command doesn't create a " + type + " output file.\n"); }
+        else {
+            if (type == "fasta")            {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "sabund")    {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "name")        {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "group")       {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "list")        {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "rabund")       {   outputFileName =  "subsample" + m->getExtension(inputName);   }
+            else if (type == "shared") {   outputFileName =  "subsample" + m->getExtension(inputName);        }
+            else { m->mothurOut("[ERROR]: No definition for type " + type + " output file tag.\n"); m->control_pressed = true;  }
+        }
+        return outputFileName;
+       }
+       catch(exception& e) {
+               m->errorOut(e, "SubSampleCommand", "getOutputFileNameTag");
+               exit(1);
+       }
+}
+
 //**********************************************************************************************************************
 SubSampleCommand::SubSampleCommand(){  
        try {
@@ -229,11 +258,11 @@ SubSampleCommand::SubSampleCommand(string option) {
                        else { 
                                pickedGroups = true;
                                m->splitAtDash(groups, Groups);
-                               m->Groups = Groups;
+                               m->setGroups(Groups);
                        }
                        
                        string temp = validParameter.validFile(parameters, "size", false);              if (temp == "not found"){       temp = "0";             }
-                       convert(temp, size);  
+                       m->mothurConvert(temp, size);  
                        
                        temp = validParameter.validFile(parameters, "persample", false);                if (temp == "not found"){       temp = "f";             }
                        persample = m->isTrue(temp);
@@ -254,6 +283,10 @@ SubSampleCommand::SubSampleCommand(string option) {
                        if ((groupfile != "") && ((fastafile != "") && (listfile != ""))) { 
                                m->mothurOut("A new group file can only be made from the subsample of a listfile or fastafile, not both. Please correct."); m->mothurOutEndLine(); abort = true; }
                        
+                       if ((fastafile != "") && (namefile == "")) {
+                               vector<string> files; files.push_back(fastafile);
+                               parser.getNameFile(files);
+                       }
                }
 
        }
@@ -349,7 +382,8 @@ int SubSampleCommand::getSubSampleFasta() {
                        
                        //takes care of user setting groupNames that are invalid or setting groups=all
                        SharedUtil* util = new SharedUtil();
-                       util->setGroups(Groups, groupMap->namesOfGroups);
+                       vector<string> namesGroups = groupMap->getNamesOfGroups();
+                       util->setGroups(Groups, namesGroups);
                        delete util;
                        
                        //file mismatch quit
@@ -422,60 +456,49 @@ int SubSampleCommand::getSubSampleFasta() {
                
                set<string> subset; //dont want repeat sequence names added
                if (persample) {
-                       for (int i = 0; i < Groups.size(); i++) {
-                               
-                               //randomly select a subset of those names from this group to include in the subsample
-                               for (int j = 0; j < size; j++) {
-                                       
-                                       if (m->control_pressed) { return 0; }
+                       //initialize counts
+                       map<string, int> groupCounts;
+                       map<string, int>::iterator itGroupCounts;
+                       for (int i = 0; i < Groups.size(); i++) { groupCounts[Groups[i]] = 0; }
+                       
+                       for (int j = 0; j < names.size(); j++) {
                                        
-                                       //get random sequence to add, making sure we have not already added it
-                                       bool done = false;
-                                       int myrand;
-                                       while (!done) {
-                                               myrand = int((float)(thisSize) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                                               
-                                               if (subset.count(names[myrand]) == 0)  { 
-                                                       
-                                                       string group = groupMap->getGroup(names[myrand]);
-                                                       if (group == "not found") { m->mothurOut("[ERROR]: " + names[myrand] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
-                                                               
-                                                       if (group == Groups[i]) {       subset.insert(names[myrand]); break;    }
-                                               }
+                               if (m->control_pressed) { return 0; }
+                                                                                               
+                               string group = groupMap->getGroup(names[j]);
+                               if (group == "not found") { m->mothurOut("[ERROR]: " + names[j] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
+                               else{
+                                       itGroupCounts = groupCounts.find(group);
+                                       if (itGroupCounts != groupCounts.end()) {
+                                               if (groupCounts[group] < size) {        subset.insert(names[j]);        groupCounts[group]++; }
                                        }
-                               }
+                               }                               
                        }
                }else {
                        
                        //randomly select a subset of those names to include in the subsample
-                       for (int j = 0; j < size; j++) {
+                       //since names was randomly shuffled just grab the next one
+                       for (int j = 0; j < names.size(); j++) {
                                
                                if (m->control_pressed) { return 0; }
                                
-                               //get random sequence to add, making sure we have not already added it
-                               bool done = false;
-                               int myrand;
-                               while (!done) {
-                                       myrand = int((float)(thisSize) * (float)(rand()) / ((float)RAND_MAX+1.0));
+                               if (groupfile != "") { //if there is a groupfile given fill in group info
+                                       string group = groupMap->getGroup(names[j]);
+                                       if (group == "not found") { m->mothurOut("[ERROR]: " + names[j] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
                                        
-                                       if (subset.count(names[myrand]) == 0)  { 
-                                               
-                                               if (groupfile != "") { //if there is a groupfile given fill in group info
-                                                       string group = groupMap->getGroup(names[myrand]);
-                                                       if (group == "not found") { m->mothurOut("[ERROR]: " + names[myrand] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
-                                                       
-                                                       if (pickedGroups) { //if hte user picked groups, we only want to keep the names of sequences from those groups
-                                                               if (m->inUsersGroups(group, Groups)) {
-                                                                       subset.insert(names[myrand]); break;
-                                                               }
-                                                       }else{
-                                                               subset.insert(names[myrand]); break;
-                                                       }
-                                               }else{ //save everyone, group
-                                                       subset.insert(names[myrand]); break;
-                                               }                                       
+                                       if (pickedGroups) { //if hte user picked groups, we only want to keep the names of sequences from those groups
+                                               if (m->inUsersGroups(group, Groups)) {
+                                                       subset.insert(names[j]); 
+                                               }
+                                       }else{
+                                               subset.insert(names[j]); 
                                        }
-                               }
+                               }else{ //save everyone, group
+                                       subset.insert(names[j]); 
+                               }                                       
+                       
+                               //do we have enough??
+                               if (subset.size() == size) { break; }
                        }       
                }
                
@@ -483,11 +506,9 @@ int SubSampleCommand::getSubSampleFasta() {
                
                string thisOutputDir = outputDir;
                if (outputDir == "") {  thisOutputDir += m->hasPath(fastafile);  }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(fastafile)) + "subsample" + m->getExtension(fastafile);
-               
+               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(fastafile)) + getOutputFileNameTag("fasta", fastafile);         
                ofstream out;
                m->openOutputFile(outputFileName, out);
-               outputTypes["fasta"].push_back(outputFileName);  outputNames.push_back(outputFileName);
                
                //read through fasta file outputting only the names on the subsample list
                ifstream in;
@@ -530,12 +551,42 @@ int SubSampleCommand::getSubSampleFasta() {
                        m->mothurOut("[ERROR]: The subset selected contained " + toString(subset.size()) + " sequences, but I only found " + toString(count) + " of those in the fastafile."); m->mothurOutEndLine();
                }
                
+               if (namefile != "") {
+                       m->mothurOut("Deconvoluting subsampled fasta file... "); m->mothurOutEndLine();
+                       
+            string outputNameFileName = thisOutputDir + m->getRootName(m->getSimpleName(namefile)) + getOutputFileNameTag("name", namefile);
+                       //use unique.seqs to create new name and fastafile
+                       string inputString = "fasta=" + outputFileName;
+                       m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
+                       m->mothurOut("Running command: unique.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
+                       m->mothurCalling = true;
+            
+                       Command* uniqueCommand = new DeconvoluteCommand(inputString);
+                       uniqueCommand->execute();
+                       
+                       map<string, vector<string> > filenames = uniqueCommand->getOutputFiles();
+                       
+                       delete uniqueCommand;
+                       m->mothurCalling = false;
+            
+            m->renameFile(filenames["name"][0], outputNameFileName);
+            m->renameFile(filenames["fasta"][0], outputFileName);
+            
+                       outputTypes["name"].push_back(outputNameFileName);  outputNames.push_back(outputNameFileName);
+
+                       m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
+                       
+                       m->mothurOut("Done."); m->mothurOutEndLine();
+               }
+               
+               outputTypes["fasta"].push_back(outputFileName);  outputNames.push_back(outputFileName);
+               
                //if a groupfile is provided read through the group file only outputting the names on the subsample list
                if (groupfile != "") {
                        
                        string groupOutputDir = outputDir;
                        if (outputDir == "") {  groupOutputDir += m->hasPath(groupfile);  }
-                       string groupOutputFileName = groupOutputDir + m->getRootName(m->getSimpleName(groupfile)) + "subsample" + m->getExtension(groupfile);
+                       string groupOutputFileName = groupOutputDir + m->getRootName(m->getSimpleName(groupfile)) + getOutputFileNameTag("group", groupfile);
                        
                        ofstream outGroup;
                        m->openOutputFile(groupOutputFileName, outGroup);
@@ -616,34 +667,13 @@ int SubSampleCommand::getNames() {
 int SubSampleCommand::readNames() {
        try {
                
-               ifstream in;
-               m->openInputFile(namefile, in);
-               
-               string thisname, repnames;
-               map<string, vector<string> >::iterator it;
-               
-               while(!in.eof()){
-                       
-                       if (m->control_pressed) { in.close(); return 0; }
-                       
-                       in >> thisname;         m->gobble(in);          //read from first column
-                       in >> repnames;                 //read from second column
-                       
-                       it = nameMap.find(thisname);
-                       if (it == nameMap.end()) {
-                               
-                               vector<string> splitRepNames;
-                               m->splitAtComma(repnames, splitRepNames);
-                               
-                               nameMap[thisname] = splitRepNames;      
-                               for (int i = 0; i < splitRepNames.size(); i++) { names.push_back(splitRepNames[i]); }
-                               
-                       }else{  m->mothurOut(thisname + " is already in namesfile. I will use first definition."); m->mothurOutEndLine();  }
-                       
-                       m->gobble(in);
-               }
-               in.close();     
-               
+        nameMap.clear();
+        m->readNames(namefile, nameMap);
+        
+        //save names of all sequences
+        map<string, vector<string> >::iterator it;
+        for (it = nameMap.begin(); it != nameMap.end(); it++) { for (int i = 0; i < (it->second).size(); i++) { names.push_back((it->second)[i]); } }
+        
                return 0;
                
        }
@@ -672,19 +702,20 @@ int SubSampleCommand::getSubSampleShared() {
                                if (thisSize < size) {  size = thisSize;        }
                        }
                }else {
-                       m->Groups.clear();
+                       m->clearGroups();
+                       Groups.clear();
                        vector<SharedRAbundVector*> temp;
                        for (int i = 0; i < lookup.size(); i++) {
                                if (lookup[i]->getNumSeqs() < size) { 
                                        m->mothurOut(lookup[i]->getGroup() + " contains " + toString(lookup[i]->getNumSeqs()) + ". Eliminating."); m->mothurOutEndLine();
                                        delete lookup[i];
                                }else { 
-                                       m->Groups.push_back(lookup[i]->getGroup()); 
+                                       Groups.push_back(lookup[i]->getGroup()); 
                                        temp.push_back(lookup[i]);
                                }
                        } 
                        lookup = temp;
-                       Groups = m->Groups;
+                       m->setGroups(Groups);
                }
                
                if (lookup.size() == 0) {  m->mothurOut("The size you selected is too large, skipping shared file."); m->mothurOutEndLine(); delete input; return 0; }
@@ -777,68 +808,28 @@ int SubSampleCommand::processShared(vector<SharedRAbundVector*>& thislookup) {
                
                string thisOutputDir = outputDir;
                if (outputDir == "") {  thisOutputDir += m->hasPath(sharedfile);  }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(sharedfile)) + thislookup[0]->getLabel() + ".subsample" + m->getExtension(sharedfile);
-               
-               
-               ofstream out;
+               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(sharedfile)) + thislookup[0]->getLabel() + getOutputFileNameTag("shared", sharedfile);        
+        SubSample sample;
+        vector<string> subsampledLabels = sample.getSample(thislookup, size);
+        
+        if (m->control_pressed) {  return 0; }
+        
+        ofstream out;
                m->openOutputFile(outputFileName, out);
                outputTypes["shared"].push_back(outputFileName);  outputNames.push_back(outputFileName);
                
-               int numBins = thislookup[0]->getNumBins();
-               for (int i = 0; i < thislookup.size(); i++) {           
-                       int thisSize = thislookup[i]->getNumSeqs();
-                       
-                       if (thisSize != size) {
-                               
-                               string thisgroup = thislookup[i]->getGroup();
-                               
-                               OrderVector* order = new OrderVector();
-                               for(int p=0;p<numBins;p++){
-                                       for(int j=0;j<thislookup[i]->getAbundance(p);j++){
-                                               order->push_back(p);
-                                       }
-                               }
-                               random_shuffle(order->begin(), order->end());
-                               
-                               SharedRAbundVector* temp = new SharedRAbundVector(numBins);
-                               temp->setLabel(thislookup[i]->getLabel());
-                               temp->setGroup(thislookup[i]->getGroup());
-                               
-                               delete thislookup[i];
-                               thislookup[i] = temp;
-                               
-                               
-                               for (int j = 0; j < size; j++) {
-                                       
-                                       if (m->control_pressed) { delete order; out.close(); return 0; }
-                                       
-                                       //get random number to sample from order between 0 and thisSize-1.
-                                       int myrand = int((float)(thisSize) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                                       
-                                       int bin = order->get(myrand);
-                                       
-                                       int abund = thislookup[i]->getAbundance(bin);
-                                       thislookup[i]->set(bin, (abund+1), thisgroup);
-                               }       
-                               delete order;
-                       }
-               }
-               
-               //subsampling may have created some otus with no sequences in them
-               eliminateZeroOTUS(thislookup);
-               
-               if (m->control_pressed) { out.close(); return 0; }
-               
+        m->currentBinLabels = subsampledLabels;
+        
                thislookup[0]->printHeaders(out);
                
                for (int i = 0; i < thislookup.size(); i++) {
                        out << thislookup[i]->getLabel() << '\t' << thislookup[i]->getGroup() << '\t';
                        thislookup[i]->print(out);
                }
-               
                out.close();
-               
-               //save mothurOut's binLabels to restore for next label
+        
+        
+        //save mothurOut's binLabels to restore for next label
                m->currentBinLabels = saveBinLabels;
                
                return 0;
@@ -855,8 +846,7 @@ int SubSampleCommand::getSubSampleList() {
                
                string thisOutputDir = outputDir;
                if (outputDir == "") {  thisOutputDir += m->hasPath(listfile);  }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(listfile)) + "subsample" + m->getExtension(listfile);
-               
+               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(listfile)) + getOutputFileNameTag("list", listfile);            
                ofstream out;
                m->openOutputFile(outputFileName, out);
                outputTypes["list"].push_back(outputFileName);  outputNames.push_back(outputFileName);
@@ -878,7 +868,8 @@ int SubSampleCommand::getSubSampleList() {
                        
                        //takes care of user setting groupNames that are invalid or setting groups=all
                        SharedUtil* util = new SharedUtil();
-                       util->setGroups(Groups, groupMap->namesOfGroups);
+                       vector<string> namesGroups = groupMap->getNamesOfGroups();
+                       util->setGroups(Groups, namesGroups);
                        delete util;
                        
                        //create outputfiles
@@ -1008,37 +999,30 @@ int SubSampleCommand::getSubSampleList() {
                //randomly select a subset of those names to include in the subsample
                set<string> subset; //dont want repeat sequence names added
                if (persample) {
-                       for (int i = 0; i < Groups.size(); i++) {
+                       //initialize counts
+                       map<string, int> groupCounts;
+                       map<string, int>::iterator itGroupCounts;
+                       for (int i = 0; i < Groups.size(); i++) { groupCounts[Groups[i]] = 0; }
+                       
+                       for (int j = 0; j < names.size(); j++) {
                                
-                               for (int j = 0; j < size; j++) {
-                                       
-                                       if (m->control_pressed) { break; }
-                                       
-                                       //get random sequence to add, making sure we have not already added it
-                                       bool done = false;
-                                       int myrand;
-                                       while (!done) {
-                                               myrand = int((float)(names.size()) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                                               
-                                               if (subset.count(names[myrand]) == 0) { //you are not already added
-                                                       if (groupMap->getGroup(names[myrand]) == Groups[i])  { subset.insert(names[myrand]); break;     }
-                                               }
+                               if (m->control_pressed) { return 0; }
+                               
+                               string group = groupMap->getGroup(names[j]);
+                               if (group == "not found") { m->mothurOut("[ERROR]: " + names[j] + " is not in your groupfile. please correct."); m->mothurOutEndLine(); group = "NOTFOUND"; }
+                               else{
+                                       itGroupCounts = groupCounts.find(group);
+                                       if (itGroupCounts != groupCounts.end()) {
+                                               if (groupCounts[group] < size) {        subset.insert(names[j]);        groupCounts[group]++; }
                                        }
-                               }
+                               }                               
                        }
                }else{
                        for (int j = 0; j < size; j++) {
                                
                                if (m->control_pressed) { break; }
                                
-                               //get random sequence to add, making sure we have not already added it
-                               bool done = false;
-                               int myrand;
-                               while (!done) {
-                                       myrand = int((float)(names.size()) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                                       
-                                       if (subset.count(names[myrand]) == 0)  { subset.insert(names[myrand]); break;   }
-                               }
+                               subset.insert(names[j]); 
                        }       
                }
                
@@ -1206,8 +1190,7 @@ int SubSampleCommand::getSubSampleRabund() {
                
                string thisOutputDir = outputDir;
                if (outputDir == "") {  thisOutputDir += m->hasPath(rabundfile);  }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(rabundfile)) + "subsample" + m->getExtension(rabundfile);
-               
+               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(rabundfile)) + getOutputFileNameTag("rabund", rabundfile);              
                ofstream out;
                m->openOutputFile(outputFileName, out);
                outputTypes["rabund"].push_back(outputFileName);  outputNames.push_back(outputFileName);
@@ -1319,10 +1302,7 @@ int SubSampleCommand::processRabund(RAbundVector*& rabund, ofstream& out) {
                                
                                if (m->control_pressed) { delete order; return 0; }
                                
-                               //get random number to sample from order between 0 and thisSize-1.
-                               int myrand = int((float)(thisSize) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                               
-                               int bin = order->get(myrand);
+                               int bin = order->get(j);
                                
                                int abund = rabund->get(bin);
                                rabund->set(bin, (abund+1));
@@ -1364,8 +1344,7 @@ int SubSampleCommand::getSubSampleSabund() {
                
                string thisOutputDir = outputDir;
                if (outputDir == "") {  thisOutputDir += m->hasPath(sabundfile);  }
-               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(sabundfile)) + "subsample" + m->getExtension(sabundfile);
-               
+               string outputFileName = thisOutputDir + m->getRootName(m->getSimpleName(sabundfile)) + getOutputFileNameTag("sabund", sabundfile);              
                ofstream out;
                m->openOutputFile(outputFileName, out);
                outputTypes["sabund"].push_back(outputFileName);  outputNames.push_back(outputFileName);
@@ -1481,10 +1460,7 @@ int SubSampleCommand::processSabund(SAbundVector*& sabund, ofstream& out) {
        
                                if (m->control_pressed) { delete order; return 0; }
                                
-                               //get random number to sample from order between 0 and thisSize-1.
-                               int myrand = int((float)(thisSize) * (float)(rand()) / ((float)RAND_MAX+1.0));
-                               
-                               int bin = order->get(myrand);
+                               int bin = order->get(j);
                                
                                int abund = rabund->get(bin);
                                rabund->set(bin, (abund+1));
@@ -1511,57 +1487,6 @@ int SubSampleCommand::processSabund(SAbundVector*& sabund, ofstream& out) {
        }
 }                      
 //**********************************************************************************************************************
-int SubSampleCommand::eliminateZeroOTUS(vector<SharedRAbundVector*>& thislookup) {
-       try {
-               
-               vector<SharedRAbundVector*> newLookup;
-               for (int i = 0; i < thislookup.size(); i++) {
-                       SharedRAbundVector* temp = new SharedRAbundVector();
-                       temp->setLabel(thislookup[i]->getLabel());
-                       temp->setGroup(thislookup[i]->getGroup());
-                       newLookup.push_back(temp);
-               }
-               
-               //for each bin
-               vector<string> newBinLabels;
-               for (int i = 0; i < thislookup[0]->getNumBins(); i++) {
-                       if (m->control_pressed) { for (int j = 0; j < newLookup.size(); j++) {  delete newLookup[j];  } return 0; }
-                       
-                       //look at each sharedRabund and make sure they are not all zero
-                       bool allZero = true;
-                       for (int j = 0; j < thislookup.size(); j++) {
-                               if (thislookup[j]->getAbundance(i) != 0) { allZero = false;  break;  }
-                       }
-                       
-                       //if they are not all zero add this bin
-                       if (!allZero) {
-                               for (int j = 0; j < thislookup.size(); j++) {
-                                       newLookup[j]->push_back(thislookup[j]->getAbundance(i), thislookup[j]->getGroup());
-                               }
-                               //if there is a bin label use it otherwise make one
-                               string binLabel = "Otu" + (i+1);
-                               if (i < m->currentBinLabels.size()) {  binLabel = m->currentBinLabels[i]; }
-                               
-                               newBinLabels.push_back(binLabel);
-                       }
-               }
-               
-               for (int j = 0; j < thislookup.size(); j++) {  delete thislookup[j];  }
-               thislookup.clear();
-               
-               thislookup = newLookup;
-               m->currentBinLabels = newBinLabels;
-               
-               return 0;
-               
-       }
-       catch(exception& e) {
-               m->errorOut(e, "SubSampleCommand", "eliminateZeroOTUS");
-               exit(1);
-       }
-}
-
-//**********************************************************************************************************************