WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / RNAforester / src / main.cpp
diff --git a/binaries/src/ViennaRNA/RNAforester/src/main.cpp b/binaries/src/ViennaRNA/RNAforester/src/main.cpp
new file mode 100644 (file)
index 0000000..58c6b3d
--- /dev/null
@@ -0,0 +1,1127 @@
+/*
+  Copyright by Matthias Hoechsmann (C) 2002-2004
+  =====================================                                   
+  You may use, copy and distribute this file freely as long as you
+  - do not change the file,
+  - leave this copyright notice in the file,
+  - do not make any profit with the distribution of this file
+  - give credit where credit is due
+  You are not allowed to copy or distribute this file otherwise
+  The commercial usage and distribution of this file is prohibited
+  Please report bugs and suggestions to <mhoechsm@TechFak.Uni-Bielefeld.DE>
+*/
+
+#include <deque>
+#include <functional>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <list>
+#include <sstream>
+#include <string>
+#include <cstring>
+#include <climits>
+#include <map>
+
+//#include <sys/timeb.h>
+#include <sys/times.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include "Arguments.h"
+#include "alignment.h"
+#include "debug.h"
+
+//#include "global_alignment.h"
+#include "treeedit.h"
+
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+#include <libxml++/libxml++.h>
+#include <libxml/xmlschemas.h>
+#include "xsd.h"
+#endif
+#endif
+
+#include "misc.h"
+#include "progressive_align.h"
+#include "rna_alignment.h"
+#include "rnaforest.h"
+#include "rnaforestsz.h"
+#include "rnafuncs.h"
+#include "rna_profile_alignment.h"
+#include "rna_algebra.h"
+#include "rnaforester_options.h"
+
+#include "alignment.t.cpp"
+//#include "global_alignment.t.cpp"
+#include "treeedit.t.cpp"
+//#include "ppforest.t.cpp"
+
+using namespace std;
+
+/* ****************************************** */
+/*          Definitions and typedefs          */
+/* ****************************************** */
+
+struct ToLower : public unary_function<char,char> {
+       char operator()(char a)
+       {
+               return tolower(a);
+       };
+};
+
+template <class L>
+void makeDotFileAli(const PPForest<L> &ppf, const RNAforesterOptions &options)
+{
+       if(options.has(RNAforesterOptions::OutputAlignmentDotFormat))
+       {
+               string filename;
+               options.get(RNAforesterOptions::OutputAlignmentDotFormat,filename,string("ali.dot"));
+               ofstream s(filename.c_str());
+               ppf.printDot(s);
+       }
+}
+
+template <class L>
+void makeDotFileInp(const PPForest<L> &ppf, const RNAforesterOptions &options, Uint count)
+{
+       if(options.has(RNAforesterOptions::MakeDotForInputTrees))
+       {
+               ostringstream ss;
+               ofstream os;
+               ss << "input" << count << ".dot";
+               os.open(ss.str().c_str());
+               ppf.printDot(os);
+               os.close();
+       }
+}
+
+static const string RNAFORESTER_VERSION = "1.5";
+static const string PROMPT = "Input string (upper or lower case); & to end for multiple alignments, @ to quit\n";
+static const string SCALE = "....,....1....,....2....,....3....,....4....,....5....,....6....,....7....,....8\n";
+
+void alignMultiple(deque<RNAProfileAlignment*> &alignList, Score &score,const RNAforesterOptions &options,RNAFuncs::AddXmlInfos &xmlInfos);
+void alignPairwise(deque<RNAForest*> &inputListPW,Score &score,const RNAforesterOptions &options,RNAFuncs::AddXmlInfos &xmlInfos);
+void cutAfterChar(string &s,char c);
+
+void editPairwise(list<RNAForestSZ*> &inputListSZ,Score &score,RNAforesterOptions &options);
+void alignPairwiseSimple(deque<RNAForest*> &inputListPW,Score &score,RNAforesterOptions &options);
+
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+extern "C" {
+  bool validateXSD(string filename);
+}
+#endif
+#endif
+
+static void showversion(const char *prog)
+{
+       cout << prog << ", version " << RNAFORESTER_VERSION << endl;
+       cout << "Copyright Matthias Hoechsmann 2001-2004," << endl << "mhoechsm@techfak.uni-bielefeld.de" << endl;
+}
+
+int main(int argc, const char **argv)
+{      
+       string buffer;
+       string baseStr,viennaStr,nameStr;
+       Ulong basePairCount,maxDepth;
+       deque<RNAForest*> inputListPW;
+       deque<RNAProfileAlignment*> alignList;
+       bool showScale=true,multipleAlign=false;
+       istream *inputStream=NULL;
+       istringstream inputString;
+       string tmpInput = "";
+       ifstream *inputFile=NULL;
+       Uint structure_count=1;
+       int suboptPercent=100;
+       double minPairProb=0.25;
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+       xmlpp::Document* xmlDoc;
+#endif
+#endif
+       string xmlOrig;
+       map<int,string> comments;
+       map<int,string> idMapping;
+       map<int,string> descriptions;
+       map<int,string> names;
+       map<int,string> synonyms;
+       int seqID = 0;
+       stringstream ss;
+       RNAFuncs::AddXmlInfos xmlInfos;
+       
+       list<RNAForestSZ*> inputListSZ;
+
+       try
+       {
+               RNAforesterOptions options(argc,argv);
+
+               // check options
+               if(options.has(RNAforesterOptions::Help))
+               {
+                       options.help();
+                       exit(EXIT_SUCCESS);
+               }
+
+               if(options.has(RNAforesterOptions::SecretHelp))
+               {
+                       options.secretHelp();
+                       exit(EXIT_SUCCESS);
+               }
+
+               if(options.has(RNAforesterOptions::Version))
+               {
+                       showversion(argv[0]);
+                       exit(EXIT_SUCCESS);      
+               }
+
+               // read score values
+               Score score(options);
+               if(!options.has(RNAforesterOptions::ShowOnlyScore))
+                       score.print();
+
+               // check option suboptimals
+               if(options.has(RNAforesterOptions::LocalSubopts))
+               {
+                       options.get(RNAforesterOptions::LocalSubopts,suboptPercent,100);
+                       if(suboptPercent<0 || suboptPercent>100)
+                       {
+                               cerr << "error: value for parameter --subopts must be in range from 0 to 100" << endl;
+                               exit(EXIT_FAILURE);
+                       }
+               }
+
+#ifdef HAVE_LIBRNA  // This features require the ViennaRNA library             
+               options.get(RNAforesterOptions::PredictMinPairProb,minPairProb,0.25);
+               if(options.has(RNAforesterOptions::PredictProfile))
+                 cout << "Minimum required basepair probability (-pmin): " << minPairProb << endl;
+#endif
+               
+               // show if suboptimals
+               if(!options.has(RNAforesterOptions::ShowOnlyScore))
+                       if(options.has(RNAforesterOptions::LocalSimilarity) && options.has(RNAforesterOptions::LocalSubopts))
+                         cout << "calculate suboptimals within " << suboptPercent << "% of global optimum" << endl << endl;
+
+               // profile search
+               if(options.has(RNAforesterOptions::ProfileSearch))
+                 {
+                   string filename;
+                   
+                   options.get(RNAforesterOptions::ProfileSearch,filename,string(""));
+                   if(filename=="")
+                     {
+                       cerr << "no profile filename" << endl;
+                       exit(EXIT_FAILURE);
+                     }
+                   
+                   RNAProfileAlignment *rnaProfileAli=new RNAProfileAlignment(filename);
+                   alignList.push_back(rnaProfileAli);
+                 }
+
+               if(options.has(RNAforesterOptions::ReadFromFile))
+               {
+                       string filename;
+                       options.get(RNAforesterOptions::ReadFromFile,filename,string(""));
+                       inputFile=new ifstream(filename.c_str());
+                       if(inputFile->fail())
+                       {
+                               cerr << "cannot open file: \"" << filename << "\"" << endl;
+                               exit(EXIT_FAILURE);
+                       }
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2                                                    
+                       // getline extracts all characters of the first line until '\n' to check whether inputFile is an xml file
+                       getline(*inputFile,buffer);
+                       
+                       // input file is an xml file 
+                       if(buffer.find("<?xml",0)==0){
+                         buffer="";
+                         
+                         // validation
+                         //if(!validateXSD(filename)){
+                         //  exit(EXIT_FAILURE);
+                         //}
+                         
+                         // create Dom parser
+                         xmlpp::DomParser domParser;
+                         domParser.parse_file(filename);
+                                                 
+                         xmlDoc = domParser.get_document();
+                         xmlpp::Element* elemRoot = xmlDoc->get_root_node();
+                         xmlpp::Node::NodeList nodeListRnaStructure = elemRoot->get_children();
+                         
+                         // for each rnastructure element
+                         xmlpp::Node::NodeList::iterator it1;
+                         xmlpp::Node::NodeList::iterator it2;
+                         xmlpp::Node::NodeList::iterator it3;
+                         for(it1=nodeListRnaStructure.begin();it1!=nodeListRnaStructure.end();it1++){
+                           if((*it1)->get_name() == "rnastructure"){
+                             seqID++;
+                             tmpInput.append(">");
+                             ss << seqID;
+                             tmpInput.append(ss.str());
+                             ss.str("");
+                             tmpInput.append("\n");
+                           }
+                                                      
+                           xmlpp::Node::NodeList nodeListSeq = (*it1)->get_children();
+                           for(it2=nodeListSeq.begin();it2!=nodeListSeq.end();it2++){
+                             if((*it2)->get_name()=="sequence"){
+                               xmlpp::Element* elemSeq = (xmlpp::Element*)(*it2);
+                               
+                               // map internal id to seqID :: JK debug
+                               cout << "seqID: " << seqID << endl;
+                               cout << "idMapping[seqID]: " << elemSeq->get_attribute("seqID")->get_value() << endl;
+                               //
+                               idMapping[seqID] = elemSeq->get_attribute("seqID")->get_value();
+
+                               xmlpp::Node::NodeList nodeListName = elemSeq->get_children();
+                               for(it3=nodeListName.begin();it3!=nodeListName.end();it3++){
+                                 if((*it3)->get_name()=="name" && ((xmlpp::Element*)(*it3))->get_child_text()){
+                                   // map the name to seqID
+                                   names[seqID] = ((xmlpp::Element*)(*it3))->get_child_text()->get_content();
+                                 }
+                                 if((*it3)->get_name()=="synonyms" && ((xmlpp::Element*)(*it3))->get_child_text()){
+                                   // map synonyms to seqID
+                                   synonyms[seqID] = ((xmlpp::Element*)(*it3))->get_child_text()->get_content();
+                                 }
+                                 if((*it3)->get_name()=="description" && ((xmlpp::Element*)(*it3))->get_child_text()){
+                                   // map the description to seqID
+                                   descriptions[seqID] = ((xmlpp::Element*)(*it3))->get_child_text()->get_content();
+                                 }
+                                 if((*it3)->get_name()=="freeSequence" || (*it3)->get_name()=="nucleicAcidSequence"){
+                                   xmlpp::Element* elemFreeSequence = (xmlpp::Element*)(*it3);
+                                   tmpInput.append(elemFreeSequence->get_child_text()->get_content());
+                                   tmpInput.append("\n");
+                                 }
+                               } // end for it3
+                             }
+                             
+                             // get comment if available
+                             if((*it2)->get_name()=="comment" && ((xmlpp::Element*)(*it2))->get_child_text()){
+                               comments[seqID] = ((xmlpp::Element*)(*it2))->get_child_text()->get_content();
+                             }
+                                                                             
+                             // get structure
+                             if((*it2)->get_name()=="structure" && ((xmlpp::Element*)(*it2))->get_child_text()){
+                               xmlpp::Element* elemStr = (xmlpp::Element*)(*it2);
+                               tmpInput.append(elemStr->get_child_text()->get_content());
+                               tmpInput.append("\n");
+                             }
+                           } // end for it2
+                           
+                         } // end for it1
+                         xmlOrig = xmlDoc->write_to_string();
+
+                         // struct with additional xml infos
+                         xmlInfos.idmapping = idMapping;
+                         xmlInfos.comments = comments;
+                         xmlInfos.descriptions = descriptions;
+                         xmlInfos.names = names;
+                         xmlInfos.synonyms = synonyms;
+                         xmlInfos.xmlInput = true;
+                                 
+                         inputString.str(tmpInput.c_str());
+                         inputStream=&inputString;
+                         
+                       } else {
+
+                         xmlInfos.xmlInput = false;
+                         // no xml file write the first line from buffer back to stream
+                         for(int i=buffer.size();i>=0;i--){
+                           inputFile->putback(buffer[i]);
+                         }
+#endif
+#endif
+                         inputStream=inputFile;
+
+#ifdef HAVE_LIBXMLPLUSPLUS     
+#ifdef HAVE_LIBXML2      
+                       }
+#endif
+#endif
+               } else {
+                 inputStream=&cin;
+               }
+               
+               if(showScale)
+                 {
+                   if(!options.has(RNAforesterOptions::NoScale) && !options.has(RNAforesterOptions::ReadFromFile))
+                     cout << endl << PROMPT << SCALE;
+                   showScale=false;
+                 }
+
+               for(;;)
+               {
+                 getline(*inputStream,buffer);
+                 
+                       if(inputStream->eof())
+                         {     
+                           if(options.has(RNAforesterOptions::Multiple) && !options.has(RNAforesterOptions::ProfileSearch))
+                               buffer="&";
+                           else
+                             exit(EXIT_SUCCESS);
+                         }
+
+                       if(buffer.empty())
+                               continue;
+
+                       // quit if character is @
+                       if(buffer[0]=='@')
+                         break;
+
+                       // delete '\r' at line end from non unix files
+                       if(buffer[buffer.size()-1]=='\r')
+                               buffer.erase(buffer.size()-1);
+
+                       // check for name of structure
+                       if(buffer[0]=='>')
+                       {
+                         /*if(buffer.find(" ",0) != string::npos){
+                           int t = buffer.find(" ",0);
+                           nameStr=&buffer[t];
+                         } else {
+                           nameStr=&buffer[1];
+                           }*/
+                         nameStr=&buffer[1];
+                         continue;
+                       }
+
+                       // cut after blank
+                       cutAfterChar(buffer,' ');
+
+                       // check for aligning multiple structures
+                       // if input is read from file the eof has the same meaning as &
+                       if( buffer[0]=='&')
+                               multipleAlign=true;
+                       else
+                       {
+                               // check for base string
+                         
+                         if(RNAFuncs::isRNAString(buffer))
+                               {
+                                 baseStr=buffer;
+                                 // convert to small letters
+                                 transform(baseStr.begin(),baseStr.end(),baseStr.begin(),ToLower());
+                                 // t -> u
+                                 replace(baseStr.begin(),baseStr.end(),'t','u');
+                                 // delete '.'  and '-' from alignment files
+                                 remove(baseStr.begin(),baseStr.end(),'.');
+                                 remove(baseStr.begin(),baseStr.end(),'-');
+
+#ifdef HAVE_LIBRNA  // This features require the ViennaRNA library                               
+                                 if(options.has(RNAforesterOptions::PredictProfile))
+                                   {
+                                     ostringstream ss;          
+                                     string constraint;
+
+                                     // if there is no name given (> ...) use a counter
+                                     if(nameStr=="")
+                                       ss << "> " << structure_count;
+                                     else
+                                       ss << nameStr;  
+                                     
+                                     cout << "Predicting structure profile for sequence: " << ss.str() << endl;
+                                     RNAProfileAlignment *rnaProfileAli=new RNAProfileAlignment(baseStr,ss.str(),constraint,minPairProb);
+                                     alignList.push_back(rnaProfileAli);
+                                     makeDotFileInp(*rnaProfileAli,options,structure_count);
+                                     structure_count++;
+                                   }
+#endif                           
+
+                                 //                              continue;
+                               }
+                         else
+                           {
+
+                               // check for vienna string      
+                         if(RNAFuncs::isViennaString(buffer,basePairCount,maxDepth))
+                           {
+
+#ifdef HAVE_LIBRNA  // This features require the ViennaRNA library                           
+                             // skip structure lines if structures are predicted
+                             if(options.has(RNAforesterOptions::PredictProfile))
+                               {
+                                 cout << "ignoring structure: " << buffer << endl;
+                                 continue;
+                               }
+#endif
+                             
+                            viennaStr=buffer;         
+                           }
+                         else   
+                               { 
+                                       cerr << "The input sequence is neither an RNA/DNA string nor in vienna format." << endl;
+                                       cerr << "line: " << buffer << endl;
+                                       showScale=true;
+                                       exit(EXIT_FAILURE);
+                               }
+
+                               // add structure to input list
+                               if(options.has(RNAforesterOptions::Multiple))
+                               {
+                                       ostringstream ss;                
+
+                                       // if there is no name given (> ...) use a counter
+                                       if(nameStr=="")
+                                         ss << "> " << structure_count;
+                                       else
+                                         ss << nameStr;        
+
+
+                                       RNAProfileAlignment *rnaProfileAli=new RNAProfileAlignment(baseStr,viennaStr,ss.str());
+                                       makeDotFileInp(*rnaProfileAli,options,structure_count);                                 
+                                       alignList.push_back(rnaProfileAli);     
+                               }
+                               else
+                               {
+                                 if(options.has(RNAforesterOptions::TreeEdit))
+                                   {
+                                     RNAForestSZ *rnaForestSZ=new RNAForestSZ(baseStr,viennaStr,nameStr);
+                                     inputListSZ.push_back(rnaForestSZ);
+                                   }
+                                 else
+                                   {
+                                     RNAForest *rnaForest=new RNAForest(baseStr,viennaStr,nameStr);                    
+                                     nameStr="";
+                                     makeDotFileInp(*rnaForest,options,structure_count);
+                                     inputListPW.push_back(rnaForest);
+                                   }
+                               }
+
+                               structure_count++;      
+                               showScale=true;
+                           }
+                       }
+
+                       // ***** multiple alignment
+                       if((options.has(RNAforesterOptions::Multiple) && multipleAlign) || (options.has(RNAforesterOptions::ProfileSearch) && alignList.size()==2))
+                       {
+                               alignMultiple(alignList,score,options,xmlInfos);
+                               multipleAlign=false;
+                               structure_count=1;
+                               
+                               if(options.has(RNAforesterOptions::ProfileSearch))
+                                 {
+                                   string filename;
+                   
+                                   options.get(RNAforesterOptions::ProfileSearch,filename,string(""));                             
+                                   RNAProfileAlignment *rnaProfileAli=new RNAProfileAlignment(filename);
+                                   alignList.push_back(rnaProfileAli);
+                                 }
+                               else
+                                 break;
+
+                               //                              break;
+                       }
+
+                       // ***** pairwise alignment
+                       if(inputListPW.size()==2)
+                       {
+                         if(options.has(RNAforesterOptions::GlobalAlignment))
+                         {
+                           alignPairwiseSimple(inputListPW,score,options);
+                         } else 
+                           alignPairwise(inputListPW,score,options,xmlInfos);
+                         break;
+                       }
+                       
+                       if(inputListSZ.size()==2)
+                       {
+                         editPairwise(inputListSZ,score,options);
+                         break;
+                       }
+
+               }
+
+               // free dynamic allocated memory
+               deque<RNAForest*>::const_iterator it;
+               for(it = inputListPW.begin(); it!=inputListPW.end(); it++){
+                 delete *it;
+               }
+
+               DELETE(inputFile);
+
+               return (0);
+       }
+       catch(RNAforesterOptions::IncompatibleException e)
+       {
+               e.showError();
+               return(EXIT_FAILURE);
+       } 
+       catch(RNAforesterOptions::RequiresException e)
+       {
+               e.showError();
+               return(EXIT_FAILURE);
+       }
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+       catch(xmlpp::validity_error ve) 
+       {
+         cout << ve.what() << endl;
+       //return(EXIT_FAILURE);
+       } 
+       catch(xmlpp::parse_error pe)
+       {
+         cout << pe.what() << endl;
+         //return(EXIT_FAILURE);
+       } 
+       catch(xmlpp::exception e)
+       {
+         cout << e.what() << endl;
+         //return(EXIT_FAILURE);
+       } 
+#endif
+#endif
+               
+}
+
+
+
+void cutAfterChar(string &s,char c){
+       string::size_type pos=s.find(c);
+       if(pos!=string::npos)
+               s.erase(pos);
+}
+
+void alignMultiple(deque<RNAProfileAlignment*> &alignList, Score &score,const RNAforesterOptions &options,RNAFuncs::AddXmlInfos &xmlInfos)
+{
+       DoubleScoreProfileAlgebraType *alg;
+       deque<pair<double,RNAProfileAlignment*> > resultList;
+//     double optScore;
+       Uint clusterNr=1;
+       double minPairProb;
+       string outputFile;
+
+       options.get(RNAforesterOptions::ConsensusMinPairProb,minPairProb,0.5);
+       
+       // distance or similarity
+       if(options.has(RNAforesterOptions::CalculateDistance))
+               alg=new DoubleDistProfileAlgebra(score);
+       else
+               alg=new DoubleSimiProfileAlgebra(score);
+
+       cout << endl;   
+
+       progressiveAlign(alignList,resultList,alg,options);
+
+       cout << endl;
+       cout << "*** Results ***" << endl << endl; 
+       cout << "Minimum basepair probability for consensus structure (-cmin): " << minPairProb << endl << endl;
+
+       deque<pair<double,RNAProfileAlignment*> >::const_iterator it;
+       for(it=resultList.begin();it!=resultList.end();it++)
+         {
+           cout << "RNA Structure Cluster Nr: " << clusterNr << endl;
+           cout << "Score: " << it->first << endl;
+           cout << "Members: " << it->second->getNumStructures() << endl << endl;
+           if(options.has(RNAforesterOptions::FastaOutput))
+             {
+               it->second->printFastaAli(false);
+               cout << endl;
+             }
+           else
+             {  
+
+               it->second->printSeqAli();
+
+#ifdef HAVE_LIBRNA  // This features require the ViennaRNA library             
+               // print alignment
+               it->second->printStrAli();
+               cout << endl;
+#endif         
+             }
+
+           // save profile
+           if(options.has(RNAforesterOptions::SaveProfile))
+           {
+             string filename;
+             filename=options.generateFilename(RNAforesterOptions::SaveProfile,".pro", "rna.pro",clusterNr);
+      it->second->save(filename);
+           }
+           
+
+               // print consensus structure
+               cout << "Consensus sequence/structure:" << endl;
+               it->second->printConsensus(minPairProb);
+               cout << endl;
+
+#ifdef HAVE_LIBG2  // This features require the g2 library             
+               // generate squiggle plots
+                       if(options.has(RNAforesterOptions::MakeSquigglePlot))
+                       {
+                               RNAProfileAlignment::SquigglePlotOptions sqOptions;
+                               string filename;
+
+                               // plot showing full base information
+                               filename=options.generateFilename(RNAforesterOptions::MakeSquigglePlot,".ps", "rnaprofile.ps",clusterNr);
+                               sqOptions.greyColors=options.has(RNAforesterOptions::SquiggleGreyColors);
+                               sqOptions.minPairProb=minPairProb;
+                               sqOptions.mostLikelySequence=false;
+                               it->second->squigglePlot(filename,sqOptions);
+
+                               // plot showing consensus sequence
+                               filename=options.generateFilename(RNAforesterOptions::MakeSquigglePlot,"_cons.ps", "rnaprofile_cs.ps",clusterNr);
+                               sqOptions.mostLikelySequence=true;
+                               it->second->squigglePlot(filename,sqOptions);
+                       }
+#endif               
+
+               clusterNr++;
+         }
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+       if(options.has(RNAforesterOptions::XmlOutputFile)){
+         options.get(RNAforesterOptions::XmlOutputFile,outputFile,string(""));
+       } else {
+         outputFile = "result.xml";
+       }
+
+       if(options.has(RNAforesterOptions::GenerateXML))
+        { 
+               RNAFuncs::printMAliXML(resultList,options,minPairProb,xmlInfos,outputFile);     
+       }
+#endif
+#endif
+
+       /*
+       if(!options.has(RNAforesterOptions::ShowOnlyScore))
+       {
+               cout << "global optimal score: ";
+       }
+       cout << optScore << endl;
+
+       list<RNAProfileAlignment*>::iterator it=inputMapProfile.begin();
+       RNAProfileAlignment *ppf=it;
+       if(!options.has(RNAforesterOptions::ShowOnlyScore))
+       {
+               // generate dot file
+               makeDotFileAli(*ppf,options);
+
+               ppf->print();
+               cout << endl;
+               ppf->printConsensus();
+       }
+       */
+
+       // save profile alignment to binary file
+       /*            if(options.has(RNAforesterOptions::SaveMultipleAliFile))
+       {
+       string filename;
+
+       filename=generateFilename(options,RNAforesterOptions::SaveMultipleAliFile,".mta", "unknown.dot");
+       ofstream s(filename.c_str());
+       f1->save(s);
+       }
+       */
+
+       /*
+       // generate squiggle plots
+       if(options.has(RNAforesterOptions::MakeSquigglePlot))
+       {
+               RNAProfileAlignment::SquigglePlotOptions sqOptions;
+               string filename;
+
+               // plot showing full base information
+               filename=options.generateFilename(RNAforesterOptions::MakeSquigglePlot,".ps", "rnaprofile.ps");
+               sqOptions.greyColors=options.has(RNAforesterOptions::SquiggleGreyColors);
+               sqOptions.mostLikelySequence=false;
+               ppf->squigglePlot(filename,sqOptions);
+
+               // plot showing consensus sequence
+               filename=options.generateFilename(RNAforesterOptions::MakeSquigglePlot,"_cons.ps", "rnaprofile_cons.ps");
+               sqOptions.greyColors=options.has(RNAforesterOptions::SquiggleGreyColors);
+               sqOptions.mostLikelySequence=true;
+               ppf->squigglePlot(filename,sqOptions);
+       }
+       */
+
+       
+       delete alg;
+}
+
+
+void alignPairwise(deque<RNAForest*> &inputListPW,Score &score,const RNAforesterOptions &options,RNAFuncs::AddXmlInfos &xmlInfos)
+{
+       IntScoreRNA_AlgebraType *alg;
+       Uint xbasepos,ybasepos,xlen,ylen;
+       list<pair<Uint,Uint> > xsubopts;
+       list<pair<Uint,Uint> > ysubopts;
+       string seq1,seq2,str1,str2;
+       char s[8];
+       int suboptPercent;
+       Uint count=1;
+       RNAFuncs::SquigglePlotOptions sqOptions;
+       tms tmsStart, tmsEnd;
+       string outputFile;
+
+       // read options
+       options.get(RNAforesterOptions::LocalSubopts,suboptPercent,100);
+
+#ifdef HAVE_LIBG2  // This features require the g2 library     
+       // generate squiggle plot
+       if(options.has(RNAforesterOptions::MakeSquigglePlot))
+       {             
+               // get sq options
+               sqOptions.hideBaseNumbers=options.has(RNAforesterOptions::SquiggleHideBaseNumbers);
+               options.get(RNAforesterOptions::SquiggleBaseNumberInterval,sqOptions.baseNumInterval,(Uint)20);
+               sqOptions.greyColors=options.has(RNAforesterOptions::SquiggleGreyColors);
+               options.get(RNAforesterOptions::SquiggleScaleFactor,sqOptions.scale,1.0);
+               sqOptions.generateFIG=options.has(RNAforesterOptions::SquiggleGenerateFIG);             
+#ifdef HAVE_LIBGD
+               sqOptions.generatePNG=options.has(RNAforesterOptions::SquiggleGeneratePNG);
+               sqOptions.generateJPG=options.has(RNAforesterOptions::SquiggleGenerateJPG);
+#endif
+               
+       }
+#endif
+       
+       // distance or similarity
+       if(options.has(RNAforesterOptions::CalculateDistance))
+               alg=new IntDistRNA_Algebra(score);
+       else
+       {
+               if(options.has(RNAforesterOptions::RIBOSUMScore))
+                       alg=new RIBOSUM8560(score);
+               else
+                       alg=new IntSimiRNA_Algebra(score);
+       }
+
+       RNAForest *f1=inputListPW.front();
+       RNAForest *f2=inputListPW.back();
+
+       if(options.has(RNAforesterOptions::SpaceTimeInfo))
+         {
+           IntScore_AlgebraType *algGlobClassic;
+
+           algGlobClassic=new IntDist_Algebra(score);
+
+           if(!options.has(RNAforesterOptions::ShowOnlyScore))
+             {
+               cout << "F1_NUMNODES" << ";";
+               cout << "F2_NUMNODES" << ";";
+               cout << "F1_DEGREE" << ";";
+               cout << "F2_DEGREE" << ";";
+               cout << "F1_LEAVES" << ";"; 
+               cout << "F2_LEAVES" << ";";
+               cout << "F1_DEPTH" << ";"; 
+               cout << "F2_DEPTH" << ";";
+               cout << "F1_NUMCSFS" << ";";
+               cout << "F2_NUMCSFS" << ";";
+               cout << "TABLE_SIZE_4D" << ";";
+               cout << "TABLE_SIZE_2D" << ";";
+               cout << "GLOBALI_TIME" << ";";
+               cout << "GLOBALI_TIME_SPEEDUP" << ";";
+               cout << "LOCALALI_TIME" << ";";
+               cout << "LOCALALI_TIME_SPEEDUP" << ";";
+               
+               cout << endl;
+             }
+
+           cout << f1->size() << "\t";
+           cout << f2->size() << "\t"; 
+           cout << f1->maxDegree() << "\t";
+           cout << f2->maxDegree() << "\t";
+           cout << f1->numLeaves() << "\t";
+            cout << f2->numLeaves() << "\t";
+           cout << f1->maxDepth() << "\t";
+           cout << f2->maxDepth() << "\t";
+           cout << f1->getNumCSFs() << "\t";
+           cout << f2->getNumCSFs() << "\t";
+           cout << f1->size()*f2->size()*f1->maxDegree()*f1->maxDegree() << "\t";
+           cout << f1->getNumCSFs()*f2->getNumCSFs() << "\t";
+
+           // global alignment
+           {
+             times(&tmsStart);
+             Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*algGlobClassic,false,true);
+             times(&tmsEnd);
+             cout <<((double) (tmsEnd.tms_utime - tmsStart.tms_utime))/sysconf(_SC_CLK_TCK) << "\t"; 
+             //            cerr << "#" << ali.getGlobalOptimum() << "#";
+           }
+
+           // global alignment speedup
+           {
+             times(&tmsStart);
+             Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*algGlobClassic,false,false);
+             times(&tmsEnd);
+             cout <<((double) (tmsEnd.tms_utime - tmsStart.tms_utime))/sysconf(_SC_CLK_TCK) << "\t"; 
+             //            cerr << "#" << ali.getGlobalOptimum() << "#";
+           }
+
+           // local alignment
+           {
+             times(&tmsStart);
+             Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*algGlobClassic,true,true);
+             times(&tmsEnd);
+             cout <<((double) (tmsEnd.tms_utime - tmsStart.tms_utime))/sysconf(_SC_CLK_TCK) << "\t"; 
+             //            cerr << "#" << ali.getLocalOptimum() << "#";
+           }
+
+           // local alignment speedup
+           {
+             times(&tmsStart);
+             Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*algGlobClassic,true,false);
+             times(&tmsEnd);
+             cout <<((double) (tmsEnd.tms_utime - tmsStart.tms_utime))/sysconf(_SC_CLK_TCK) << "\t"; 
+             //            cerr << "#" << ali.getLocalOptimum() << "#";
+           }
+           
+
+           cout << endl;
+
+           exit(EXIT_SUCCESS);
+         }
+       
+       Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*alg);
+       RNA_Alignment ppfali;
+       ppfali.setStructureNames(f1->getName(),f2->getName());
+       double optScore;
+
+
+       if(!options.has(RNAforesterOptions::ShowOnlyScore))
+       {
+         if(options.has(RNAforesterOptions::SmallInLarge))
+           {
+             cout << "small-in-large optimal score: ";
+           }
+         else
+           {
+             if(options.has(RNAforesterOptions::LocalSimilarity))
+               cout << "local optimal score: ";
+             else
+               cout << "global optimal score: ";
+           }
+       }
+
+       if(options.has(RNAforesterOptions::SmallInLarge))
+         {
+           cout << ali.getSILOptimum() << endl;
+           optScore = ali.getSILOptimum();
+         }
+       else
+         {
+           if(options.has(RNAforesterOptions::LocalSimilarity))
+             {
+               cout << ali.getLocalOptimum() << endl;
+               optScore = ali.getLocalOptimum();
+             }  
+           else
+             {
+               cout << ali.getGlobalOptimum() << endl;
+               optScore = ali.getGlobalOptimum();
+               if(options.has(RNAforesterOptions::RelativeScore))
+                 cout << ali.getGlobalOptimumRelative() << endl;
+             }
+         }
+
+
+       if(!options.has(RNAforesterOptions::ShowOnlyScore))
+       {
+         if(options.has(RNAforesterOptions::SmallInLarge))
+           {
+             ali.getOptSILAlignment(ppfali,ybasepos);
+             cout << "starting at position: " << ybasepos << endl << endl; 
+           }
+         else
+           {         
+             if(options.has(RNAforesterOptions::LocalSimilarity))
+               {
+                 ali.resetOptLocalAlignment(suboptPercent);
+                 ali.getOptLocalAlignment(ppfali,xbasepos,ybasepos);                               
+                 cout << "starting at positions: " << xbasepos << "," << ybasepos << endl << endl; 
+                 xmlInfos.xbasepos = xbasepos;
+                 xmlInfos.ybasepos = ybasepos;
+               }
+             else                
+               ali.getOptGlobalAlignment(ppfali);                
+           }
+
+               // generate dot file
+               makeDotFileAli(ppfali,options);
+
+               // print alignment
+               ppfali.getSequenceAlignments(seq1,seq2);                                
+               ppfali.getStructureAlignment(str1,true);
+               ppfali.getStructureAlignment(str2,false);
+
+               if(options.has(RNAforesterOptions::FastaOutput)){
+                 cout << ppfali.getStructureNameX() << endl;
+                 cout << seq1 << endl;
+                 cout << str1 << endl;
+                 cout << ppfali.getStructureNameY() << endl;
+                 cout << seq2 << endl;
+                 cout << str2 << endl;
+                 cout << endl;
+               }
+               else {
+                 RNAFuncs::printAli(ppfali.getStructureNameX(),ppfali.getStructureNameY(),seq1,seq2,str1,str2);
+               }
+
+               xlen=seq1.size();
+               ylen=seq2.size();
+               if(options.has(RNAforesterOptions::LocalSimilarity))
+               {
+                       xsubopts.push_back(pair<Uint,Uint>(xbasepos,xlen));
+                       ysubopts.push_back(pair<Uint,Uint>(ybasepos,ylen));
+               }
+
+#ifdef HAVE_LIBG2  // This features require the g2 library             
+               if(options.has(RNAforesterOptions::MakeSquigglePlot))
+                 {
+                   sprintf(s,"%d",count);
+                   ppfali.squigglePlot(s,sqOptions);      
+                 }
+#endif        
+
+               // suboptimal alignments
+               if(options.has(RNAforesterOptions::LocalSubopts))
+               {
+                       while(ali.nextLocalSuboptimum())
+                       {
+                               count++;
+                               cout << "local optimal score: ";
+                               cout << ali.getLocalOptimum() << endl;
+                               ali.getOptLocalAlignment(ppfali,xbasepos,ybasepos);
+                               cout << "starting at positions: " << xbasepos << "," << ybasepos << endl << endl; 
+
+                               // print alignment
+                               ppfali.getSequenceAlignments(seq1,seq2);
+                               ppfali.getStructureAlignment(str1,true);
+                               ppfali.getStructureAlignment(str2,false);
+                               RNAFuncs::printAli(ppfali.getStructureNameX(),ppfali.getStructureNameY(),seq1,seq2,str1,str2);  
+                               xlen=seq1.size();
+                               ylen=seq2.size();
+                               xsubopts.push_back(pair<Uint,Uint>(xbasepos,xlen));
+                               ysubopts.push_back(pair<Uint,Uint>(ybasepos,ylen));     
+
+#ifdef HAVE_LIBG2  // This features require the g2 library             
+                               if(options.has(RNAforesterOptions::MakeSquigglePlot))             
+                               {
+                                 sprintf(s,"%d",count);                                
+                                 ppfali.squigglePlot(s,sqOptions);                       
+                               }
+#endif                        
+                       }
+               }
+
+       }
+
+#ifdef HAVE_LIBRNA  // This features require the ViennaRNA library     
+#ifdef HAVE_LIBXMLPLUSPLUS
+#ifdef HAVE_LIBXML2
+       // generate xml
+       if(options.has(RNAforesterOptions::XmlOutputFile)){
+         options.get(RNAforesterOptions::XmlOutputFile,outputFile,string(""));
+       } else {
+         outputFile = "result.xml";
+       }
+       if(options.has(RNAforesterOptions::GenerateXML))
+       {
+         RNAFuncs::printPAliXML(ppfali.getStructureNameX(),ppfali.getStructureNameY(),seq1,seq2,str1,str2,optScore,options,xmlInfos,outputFile);
+       }
+#endif 
+#endif
+#endif
+
+#ifdef HAVE_LIBG2  // This features require the g2 library
+       // generate squiggle plot
+       if(options.has(RNAforesterOptions::MakeSquigglePlot))
+       {
+               f1->plot2d("x_str", xsubopts, sqOptions);
+               f2->plot2d("y_str", ysubopts, sqOptions);  
+       }
+#endif 
+
+       // clear input list
+       deque<RNAForest*>::const_iterator it;
+       for(it = inputListPW.begin(); it!=inputListPW.end(); it++)
+               delete *it;
+       inputListPW.clear();
+       delete alg;
+}
+
+
+void editPairwise(list<RNAForestSZ*> &inputListSZ,Score &score,RNAforesterOptions &options)
+{
+  //  timeb t1,t2;
+  IntScoreSZAlgebraType *alg;
+
+//  if(options.has(RNAforesterOptions::CalculateDistance))
+    alg=new IntDistSZAlgebra(score);
+//  else
+//    alg=new IntSimiSZAlgebra(score);
+  
+  RNAForestSZ *f1=inputListSZ.front();
+  RNAForestSZ *f2=inputListSZ.back();
+
+  //  ftime(&t1);
+  Mapping<int,RNA_Alphabet> mapping(f1,f2,*alg);
+  //  ftime(&t2);
+
+//     f1->printParameters("F1");
+//     f2->printParameters("F2");
+
+  cout << "Global optimum: " << mapping.getGlobalOptimum() << endl;
+  //  cout << "Calculation Time ms: " << (t2.time*1000+t2.millitm) - (t1.time*1000+t1.millitm) << endl;
+}
+
+
+
+void alignPairwiseSimple(deque<RNAForest*> &inputListPW,Score &score,RNAforesterOptions &options)
+{
+  //  timeb t1,t2;
+  IntScore_AlgebraType *alg;
+
+  //  if(options.has(RNAforesterOptions::CalculateDistance))
+    alg=new IntDist_Algebra(score);
+//  else
+//    alg=new ScoreAlgebraSimple(score);
+
+  RNAForest *f1=inputListPW.front();
+  RNAForest *f2=inputListPW.back();
+
+  //  ftime(&t1);
+  Alignment<int,RNA_Alphabet,RNA_AlphaPair> ali(f1,f2,*alg,false);
+  //  ftime(&t2);
+
+//     f1->printParameters("F1");
+  //f2->printParameters("F2");
+
+  cout << "Global optimum: " << ali.getGlobalOptimum() << endl;
+  //  cout << "Calculation Time ms: " << (t2.time*1000+t2.millitm) - (t1.time*1000+t1.millitm) << endl;
+}
+
+#ifdef HAVE_LIBXML2
+#ifdef HAVE_LIBXMLPLUSPLUS
+extern "C" {
+  bool validateXSD(string filename){
+    xmlSchemaParserCtxtPtr ctxt;
+    xmlSchemaValidCtxtPtr valCtxt;
+    xmlSchemaPtr schema;
+    int val;
+
+    ctxt = xmlSchemaNewMemParserCtxt(XSD_STRING,sizeof(XSD_STRING));
+        
+    schema = xmlSchemaParse(ctxt);
+    
+    valCtxt = xmlSchemaNewValidCtxt(schema);
+
+    val = xmlSchemaValidateFile(valCtxt,filename.c_str(),0);
+
+    if(val==0){
+      return true;
+    } else {
+      return false;
+    }
+  } 
+}
+#endif
+#endif
+