// cjt
// v3.3.8
// 24-1-11

import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.security.*;
import java.math.*;
import java.net.*;

import jargs.CmdLineParser;


public class searchMiRNA
{
    private static CmdLineParser parser;

    //-mandatory
    private static String opt_databasefile;
    private static String opt_targetsequence;
    private static String opt_outpath;
    private static String opt_genesplicerdata;
    private static String opt_resultname;

    //-optional
    private static int opt_fiveprimeExtension;
    private static int opt_threeprimeExtension;
    private static double opt_evalue;
    private static int opt_wvalue;
    private static int opt_minmirnaLength;
    private static int opt_maxmirnaLength;





    private static void printInfo()
    {
        System.err.println();
        System.out.println("SplamiR - Prediction of spliced miRNAs in plants.");
        System.out.println("searchMiRNA, v3.3.6");
        System.out.println("-------------------------------------------------");
        System.out.println("");
    }

    private static void printUsage()
    {
        System.err.println();
        System.err.println(
            "Usage: java -Xms512M -Xmx1024M searchMiRNA [-d,--output-dir] [-i,--database-file] [-t,--target-sequence] [-s,--GeneSplicer-data] [{-e,--e-value}] [{-w,--w-value}] [{-x,--fiveprimeExtension}] [{-y,--threeprimeExtension}] [{-n,--min-miRNA-length}] [{-m,--max-miRNA-length}]");
        System.err.println();
        System.err.println("Mandatory parameters:");
        System.err.println("  output-dir: directory to store the results");
        System.err.println("  database-file: location of blast database file (.nin|.nsg|.nhr)");
        System.err.println("  target-sequence: target FASTA file");
        System.err.println("  GeneSplicer-data: provided training set (e.g. rice)");
        System.err.println();
        System.err.println("Optional parameters:");
        System.err.println("  e-value: BLAST threshold (default: 10.0)");
        System.err.println("  w-value: BLAST initial word length (default: 9)");
        System.err.println("  fiveprimeExtension: number of genomic nt added to the start of precursor (default: 65)");
        System.err.println("  threeprimeExtension: number of genomic nt added to the end of precursor (default: 65)");
        System.err.println("  min-miRNA-length: minimum size of size of precursor after removal of intron (default: 16)");
        System.err.println("  max-miRNA-length: maximum size of size of precursor after removal of intron (default: 1000)");
    }







    public static void main (String[] args)
    {

        printInfo();

        parser = new CmdLineParser();
        readParams(args);
        integrityCheck();

        System.out.print("Identifying complementary sequence pairs in database");
		searchDatabaseWithTargetGene();
        System.out.println("...done.");
 
        System.out.print("Searching putative pri-u-miRNAs");
        if (getSequenceOfMirnaMatches()==0)
        {
            System.out.println("...done. No micro-RNAs found in database.");
            System.out.println("\nFinished.\n");            
            System.exit(0);
        }
        System.out.println("...done.");
        
        
        System.out.print("Predicting splice sites");               
        Stack<String> blastResultHits=new Stack<String>();
   		findFiles(new File(opt_outpath+"/pri-u-miRNAs/"), ".fasta","", blastResultHits);

        String filename;
        while(!blastResultHits.empty())
        {
            filename=blastResultHits.pop();
            splicing(filename);
        }
        System.out.println("...done.");        

        Stack<String> spliceResultHits=new Stack<String>();
   		findFiles(new File(opt_outpath+"/splicevariants/"), ".fasta_","", spliceResultHits);
        if (spliceResultHits.empty())
        {
            System.out.println("\tNo splice variants detected.");
            System.out.println("\nFinished.\n");            
        }



        System.out.println("Classifying variants");
        while(!spliceResultHits.empty())
        {
            filename=spliceResultHits.pop();
            int errorcode = classification(filename);

            //check for server errors!
            if (errorcode!=0)
            {
                System.out.print("\n\tmir-Abela server error. Waiting 30s to re-do and proceed...");
                spliceResultHits.push(filename);
                try {
                    Thread.sleep(30000);
                }
                catch(InterruptedException e) {}
            }
        }
        System.out.println("...done.");
        

        System.out.print("Writing results to file");
        collectResults();
        System.out.println("...done.");
        
        System.out.println("\nFinished.\n");
    }











    /* STEP 6
     *
     */
    public static void searchDatabaseWithTargetGene()
    {

        String output=runCommand("RNAblast/blastallrna -p blastn -e 100 -W "+opt_wvalue+" -d "+
        opt_databasefile+"_database.fasta -i "+ opt_targetsequence);

        String filename=opt_outpath+"/databasematch.blast";

        try
        {
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filename));
            bufferedWriter.write(output);
            bufferedWriter.close();
        }
        catch (Exception e)
        {
            System.err.println("\nERROR. Problems writing rnablast results to file:\n");
            System.err.println(e);
            e.printStackTrace();
            System.exit(0);
        }
    }









    /* STEP 7
     *
     * takes blast output file as input
     * filtering for matches with ID and start/end position
     *
     * returns multiple fasta file
     * output to several txt-files for further processing with genesplicer
     *
     *
     * filter dupl from database
     * add +/-65nt for genesplicer window size (= var fiveprime/threeprime)
     *
     */

    public static int getSequenceOfMirnaMatches()
    {
        //input files
        String databasematch=opt_outpath+"/databasematch.blast";
        String genomicfile=opt_databasefile+".plain"; //plain database file

        String line, oldline="";
        String blastmatchpos;

        int seqlen=0;
        float evalue2=0;

        File file;
        Writer output;

        String seqname="";
        char plusMinus='/'; //unknown right now

        boolean tocontinue=true;


        Stack<String> listOfBlastHits = new Stack<String>();
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(databasematch)));
            while ((line =  br.readLine()) != null)
            {
                if (line.length()>0 && line.charAt(0)=='>')
                {
                    seqname=line.trim();

                    tocontinue=true;

                    //fetch following name lines
                    while (tocontinue && (line=br.readLine())!=null)
                    {
                        //if (line== null) {System.err.println("Unexpected end of file."); System.exit(-1);}
                        if (line.length()>0 && line.indexOf("Length")<0)
                        {
                            seqname+=" "+line.trim();
                        }
                        else
                        {
                            //System.out.println(seqname);
                            tocontinue=false;
                        }
                    }


                    tocontinue=true;

                    //read ahead to get length of mir to target alignment
                    while (tocontinue && ((line=br.readLine())!=null))
                    {
                        //System.err.println("----   "+line);

                        if (line.length()>0 && line.indexOf("Strand = Plus / Plus")>=0)
                        {
                            //System.err.println("set to plus\n");
                            plusMinus='+';
                            tocontinue=false;
                        }
                        else if (line.length()>0 && line.indexOf("Strand = Plus / Minus")>=0)
                        {
                            //System.err.println("set to minus\n");
                            plusMinus='-';
                            tocontinue=false;
                        }
                        else if (line.indexOf("Identities")>0)
                        {
                            seqlen=Integer.parseInt(line.substring(line.lastIndexOf('/')+1, line.lastIndexOf('(')-1));
                            //System.err.println(seqlen+"\n");
                        }
                        else if (line.indexOf("Expect")>0)
                        {
                            String eva=line.substring(line.lastIndexOf('=')+1, line.length());

                            try
                            {
                                if (eva.charAt(0)=='e') eva="1"+eva;
                                evalue2 = Float.parseFloat(eva);
                            }
                            catch (IllegalArgumentException e)
                            {
                                System.out.println("e-value parsing error: "+eva+". Assuming e=0.0");
                                evalue2=0.0f;
                            }

                            seqname+=" target-e-value="+evalue2;
                        }
                    }


                    //System.out.println(seqname);


                    if (evalue2>opt_evalue)
                    {
                        //System.out.println("skip: evalue");
                        skipped++;
                    }
                    else if(seqlen<opt_minmirnaLength)
                    {
                        //System.out.println("skip: minsize");
                        skipped++;
                    }
                    else
                    {
                        addtostack(plusMinus+seqname.substring(seqname.lastIndexOf(" [")+2,seqname.lastIndexOf("]")), seqname);
                    }


                }
            }

        }
        catch (IOException e)
        {
            System.err.println("ERROR: Unable to read input file");
            e.printStackTrace();
            System.exit(0);
        }


        //getGrameneLink();

        return getSequFromStackStoredPos2File();
    }













    /* STEP 8
     * takes sequence as fasta file 
     * requires name of training set for splicing
     *
     * returns multiple fasta file
     *
     */
    public static void splicing(String filename)
    {
        int	minDonor=70,
            maxAcceptor=70,
            matchnumber=0;
        String datasetname="GeneSplicer/"+opt_genesplicerdata;
        String command = "GeneSplicer/bin/linux/genesplicer "+filename+" "+datasetname+" -a -30 -d -30";


        String output=runCommand(command);
        String fileID="";
        String tempSequ="";

        String path=opt_outpath+"/splicevariants/";

        String filename2= filename.substring(filename.lastIndexOf("/")+1, filename.length());


        File dir = new File(path);
        if(!dir.exists()) {if (!dir.mkdir()) System.out.println("\nERROR generating directory "+dir);}

        try
        {
            BufferedReader bro = new BufferedReader(new FileReader(filename));
			// !!!! annahme: nur zweite zeile enthaelt sequenz !!!
            fileID= bro.readLine(); //skip 1st line
            tempSequ= bro.readLine(); //take the sequence
            bro.close( );
        }
        catch (Exception e)
        {
            System.err.println("ERROR. Problems reading file:\n\t"+e.toString());
            System.exit(0);
        }

        int pos=0;

        TreeMap<Double,Integer> donor = new TreeMap<Double,Integer> ();
        TreeMap<Double,Integer> acceptor = new TreeMap<Double,Integer> ();




        Pattern p = Pattern.compile( "(\\d+) (\\d+) (.*) (.*) (.*)" );
        Matcher m1 = p.matcher(output);
        //boolean b = m.matches();

        while(m1.find())
        {
//				System.out.println(m1.group(1)+"\t"+m1.group(2)+"\t"+m1.group(3)+"\t"+m1.group(4)+"\t"+m1.group(5));

            if (Integer.parseInt(m1.group(1))>Integer.parseInt(m1.group(2)))
            {
//					System.out.println("skip direction.");
            }
            else if (m1.group(5).equalsIgnoreCase("donor"))
            {
                //pos -1 because genesplicer starts with offset 1
                pos=Integer.parseInt(m1.group(1))-1;
                if (pos<minDonor)
                {
                    //System.out.println("skip minDonor: " + pos +" in " +tempSequ.length() + " @ min "+minDonor);
                }
                else
                {
                    donor.put(0-Double.parseDouble(m1.group(3)),pos);
//System.err.println("-------------don "+pos);
                }
            }
            else //acceptor
            {
                pos=Integer.parseInt(m1.group(1))-1;
                if (pos>(tempSequ.length()-maxAcceptor))
                {
                    //System.out.println("skip maxAcceptor: " + pos +" in " +tempSequ.length() + " @ max "+maxAcceptor);
                }
                else
                {
                    acceptor.put(0-Double.parseDouble(m1.group(3)),pos);
//System.err.println("++++++++++++++acc "+pos+m1.group(3));
                }
            }


        }


        File file;
        Writer outputfile;

        for ( Map.Entry<Double, Integer> d : donor.entrySet() )
        {
            for ( Map.Entry<Double, Integer> a : acceptor.entrySet() )
            {

//				System.out.println("values: "+ d.getValue() + "\t"+ a.getValue());
                if (d.getValue()<a.getValue()) //donor comes first
                {
                    if ((tempSequ.substring(0, d.getValue())+tempSequ.substring(a.getValue()+2, tempSequ.length())).length()>
                    opt_maxmirnaLength)
                    {
                        //System.out.println("skip: length");
                    }
                    else
                    {
                        try
                        {
                            outputfile = new BufferedWriter(new FileWriter(path+filename2+"_"+(matchnumber++)));
                            outputfile.write(fileID + " splice="+d.getValue()+":"+(a.getValue()+2)+"\n");
                            outputfile.write(tempSequ.substring(0, d.getValue())+tempSequ.substring(a.getValue()+2, tempSequ.length()));
                            outputfile.flush();
                            outputfile.close();
                        } catch (IOException e)
                        {
                            System.out.println("IOException:");
                            e.printStackTrace();
                        }
                    }

                }

            }

        }



        //write unspliced file
        if (!(tempSequ.length()>opt_maxmirnaLength))
        {
            try
            {
                outputfile = new BufferedWriter(new FileWriter(path+filename2+"_unspliced"));
                outputfile.write(fileID + "- [0:0]\n");
                outputfile.write(tempSequ);
                outputfile.flush();
                outputfile.close();
            } catch (IOException e)
            {
                System.out.println("IOException:");
                e.printStackTrace();
            }
        }

    }













    /* STEP 9
     *
     * Classification of input fasta file
     * Here: sends to the miR-abela webserver and fetches the output
     * output as html result
     *
     */
    public static int classification(String filename)
    {
        StringBuilder htmlResult = new StringBuilder();
        StringBuffer input = new StringBuffer(1000);
        String line;

        String path=opt_outpath+"classification/";
        File dir = new File(path);
        if(!dir.exists()) {if (!dir.mkdir()) System.out.println("\nERROR generating directory "+dir);}
        
        String filename2= filename.substring(filename.lastIndexOf("/")+1, filename.length());
        System.out.println("Processing "+filename);

        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
            while ((line =  br.readLine()) != null)
            {
                input.append(line.trim()+"\n");
            }
            br.close();
        }
        catch (IOException e)
        {
            System.out.println("ERROR: Unable to read input file: "+e.toString());
            System.exit(-1);
        }
// {System.err.println("")

        try {

            String theCGI = "http://www.mirz.unibas.ch/cgi/miRNA.cgi?";

            String encoded =
                "email&"+
                "textArea="+URLEncoder.encode(input.toString(), "UTF-8")+"&"+
                "padding="+URLEncoder.encode("pred_miRNA_genes.cgi?padding=NONPAIRING", "UTF-8")+"&"+
                "organism=HUMAN&"+
                "windowLength=500&"+
                "windowLength&"+
                "threshold=0&"+
                "view=table";


            URL CGIurl = new URL(theCGI);

            URLConnection c = CGIurl.openConnection();
            c.setDoOutput(true);
            c.setUseCaches(false);
            c.setRequestProperty("content-type","application/x-www-form-urlencoded");
            DataOutputStream out = new DataOutputStream(c.getOutputStream());
            out.writeBytes(encoded);
            out.flush();
            out.close();

            BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));

            String aLine;
            while ((aLine = in.readLine()) != null)
            {
                // data from the CGI
                //System.out.println(aLine);
                htmlResult.append(aLine);
            }

        }
        catch (MalformedURLException e)
        {
            // Print out the exception that occurred
            System.err.println("Invalid URL "+e.getMessage());
        }
        catch (IOException e)
        {
            // Print out the exception that occurred
            System.err.println("Unable to execute "+e.getMessage());
        }


        //write results to file
        String htmlResultS=htmlResult.toString();
        String outfilename;
        try
        {
            if (!htmlResultS.contains("No results found"))
            {
                outfilename=path+filename2+"_mirAbela-pos.html";
            }
            else
            {
                outfilename=path+filename2+"_mirAbela-neg.html";
            }
            
            BufferedWriter output = new BufferedWriter(new FileWriter(outfilename));
            output.write(htmlResultS);
            output.flush();
            output.close();
        }
        catch (IOException e)
        {
            System.err.println("ERROR. Problems writing mir-Abela results to file:\n\t"+e.toString());
            System.exit(0);
        }


        //check results
        if (htmlResultS.contains("miRNA prediction results"))	{
            return 0;   //found something
        }
        else if (htmlResultS.contains("No results found"))		{
            return 0;   //found nothing
        }
        else if (htmlResultS.contains("Batch processing is expected")) {
            return 0;   //too long
        }

        //else

        System.out.println(htmlResultS);

        return -1;
    }










    public static void filteringOutput(String filename, Stack<String[]> resultStack)
    {
        String result=""; //max 2 lines to read...

        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));

            String temp;

            while ((temp = br.readLine()) != null) result=result+temp+"\n";
        }
        catch (IOException e) {
            System.err.println(e);
        }


        if (result.contains("No results found.")) return;


        //remove header
        result=result.substring(result.indexOf("structure")+9, result.length());
        System.out.println(result);
        result=Pattern.compile("<[^>]*>|\\||\\[|\\]").matcher(result).replaceAll(" # ");
        System.out.println(result);
        result=Pattern.compile("(#\\s*#\\s*)+").matcher(result).replaceAll("#");
        System.out.println(result);

        //split data
        String data[]=new String[18];

        String[] x = Pattern.compile("#").split(result);

        for (int i=0; i<(x.length); i++)
        {
            System.out.println(i+"\t"+x[i]);
        }


        for (int i=0; i<=(x.length/18); i++)
        {
            data=new String[18];
            for (int line=2; line<18; line++)
            {
                data[line-2]=x[line];
                System.out.println("\t"+line+"\t"+i + " \t" + x[line]);
            }


            resultStack.push(data);
        }

        return;
    }




    /*
     *  Helper procedure to load instructions from cmd line
     */
    private static void readParams(String[] args)
    {
        //define cmd line options
        //-mandatory
        CmdLineParser.Option opt_outpath1 = parser.addStringOption('d', "output-dir");
        CmdLineParser.Option opt_databasefile1 = parser.addStringOption('i', "database-file"); //file *_database without _plain/nin/...
        CmdLineParser.Option opt_targetsequence1 = parser.addStringOption('t', "target-sequence");
        CmdLineParser.Option opt_genesplicerdata1 = parser.addStringOption('s', "GeneSplicer-data");


        //-optional
        CmdLineParser.Option opt_fiveprimeExtension1 = parser.addIntegerOption('x', "fiveprimeExtension");
        CmdLineParser.Option opt_threeprimeExtension1 = parser.addIntegerOption('y', "threeprimeExtension");
        CmdLineParser.Option opt_evalue1 = parser.addDoubleOption('e', "e-value");
        CmdLineParser.Option opt_wvalue1 = parser.addIntegerOption('w', "w-value");
        CmdLineParser.Option opt_minmirnaLength1 = parser.addIntegerOption('n', "min-miRNA-length");
        CmdLineParser.Option opt_maxmirnaLength1 = parser.addIntegerOption('m', "max-miRNA-length");

        //read params
        try
        {
            parser.parse(args);
        }
        catch ( CmdLineParser.OptionException e )
        {
            System.err.println("ERROR parsing parameters:");
            System.err.println(e.getMessage());
            printUsage();
            System.exit(2);
        }


        //-mandatory
        opt_databasefile=(String)parser.getOptionValue(opt_databasefile1);
        opt_targetsequence=(String)parser.getOptionValue(opt_targetsequence1);
        opt_outpath=(String)parser.getOptionValue(opt_outpath1);
        opt_genesplicerdata=(String)parser.getOptionValue(opt_genesplicerdata1);

        //-optional
        opt_fiveprimeExtension=(Integer)parser.getOptionValue(opt_fiveprimeExtension1, new Integer(65));
        opt_threeprimeExtension=(Integer)parser.getOptionValue(opt_threeprimeExtension1, new Integer(65));
        opt_evalue=(Double)parser.getOptionValue(opt_evalue1, new Double(10.0));
        opt_wvalue=(Integer)parser.getOptionValue(opt_wvalue1, new Integer(9));
        opt_minmirnaLength=(Integer)parser.getOptionValue(opt_minmirnaLength1, new Integer(16));
        opt_maxmirnaLength=(Integer)parser.getOptionValue(opt_maxmirnaLength1, new Integer(1000));

        //something missing?
        if(opt_databasefile==null)
        {
            System.err.println("ERROR: No database specified.");
            printUsage();
            System.exit(2);
        }





        //check for database files
        if (opt_databasefile.endsWith(".nin") || opt_databasefile.endsWith(".nsq") || opt_databasefile.endsWith(".nhr") )
        {
            opt_databasefile=opt_databasefile.substring(0,opt_databasefile.lastIndexOf("_database.fasta"));
        }
        else
        {
            System.err.println("ERROR: No database specified. Please enter .nin, .nsg, or .nhr file.");
            printUsage();
            System.exit(2);
        }

        //do we have all database files?
        if (!(new File(opt_databasefile+".plain").isFile()))
        {
            System.err.println("ERROR: Database file ('"+opt_databasefile+".plain') is missing.");
            printUsage();
            System.exit(5);
        }
        if (!new File(opt_databasefile+"_database.fasta.nhr").isFile() || !new File(opt_databasefile+"_database.fasta.nin").isFile()  || !new File(opt_databasefile+"_database.fasta.nsq").isFile() )
        {
            System.err.println("ERROR: Database files [.nin|.nsg|.nhr] are missing.");
            printUsage();
            System.exit(5);
        }







        
        if(opt_targetsequence==null)
        {
            System.err.println("ERROR: No target specified.");
            printUsage();
            System.exit(2);
        }
        if(opt_outpath==null)
        {
            System.err.println("ERROR: No output directory specified.");
            printUsage();
            System.exit(2);
        }
        if(opt_genesplicerdata==null)
        {
            System.err.println("ERROR: No GeneSplicer training set specified.");
            printUsage();
            System.exit(2);
        }


        if (opt_outpath.substring(opt_outpath.length()-1)!="/")
        {
            opt_outpath+="/";
        }




        if (!(new File(opt_targetsequence).isFile()))
        {
            System.err.println("ERROR: Target sequence ('"+opt_targetsequence+"') is missing.");
            printUsage();
            System.exit(5);
        }




        File f = new File(opt_targetsequence);
        int filenameend=f.getName().lastIndexOf(".");
        if (filenameend==-1) filenameend=f.getName().length();
        opt_resultname = f.getName().substring(Math.max(f.getName().lastIndexOf("/"),0), filenameend);


        //avoid overwriting files
        File path=new File(opt_outpath);
        if (path.isDirectory())
        {
            File[] listOfFiles = path.listFiles();
            if(listOfFiles.length>=1)
            {
                System.err.println("ERROR: Output path ('"+opt_outpath+"') is not empty.");
                printUsage();
                System.exit(5);
            }
        }
        else
        {
            //create folder
            path.mkdirs();
        }


        //Output the list to the console
        System.out.println("Configuration:");
        System.out.println("\tdb-name= "+opt_databasefile);
        System.out.println("\ttarget= "+opt_targetsequence);
        System.out.println("\toutput-dir= "+opt_outpath);
        System.out.println("\tGeneSplicer training set= "+opt_genesplicerdata);

        System.out.println("\te-value= "+opt_evalue);
        System.out.println("\tw-value= "+opt_wvalue);
        System.out.println("\tfiveprimeExtension= "+opt_fiveprimeExtension);
        System.out.println("\tthreeprimeExtension= "+opt_threeprimeExtension);
        System.out.println("\tminmirnaLength= "+opt_minmirnaLength);
        System.out.println("\tmaxmirnaLength= "+opt_maxmirnaLength);

    }





    /*
     * Helper function to find all files in given directory and below
     * returns stack with files matching given criteria
     */
    static void findFiles(File aFile, String infilter, String outfilter, Stack <String>lifo)
    {
        if(aFile.isFile())
        {
            if (aFile.getName().contains(infilter) && (!aFile.getName().contains(outfilter) || outfilter==""))
            {
                lifo.push(aFile.getPath());
            }
        }
        else if (aFile.isDirectory())
        {
            File[] listOfFiles = aFile.listFiles();
            if(listOfFiles!=null)
            {
                for (int i = 0; i < listOfFiles.length; i++)
                {
                    findFiles(listOfFiles[i], infilter, outfilter, lifo);
                }
            }
        }
    }







    //static int i=0;

    /*
     * Helper function to execute commands
     * returns command line output
     */
    static private String runCommand(String cmd)
    {
        StringBuilder result = new StringBuilder();

        try
        {
            // Get handles for the process
            Process proc = Runtime.getRuntime().exec(cmd);

            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));

            String temp;

            //System.out.println((i++) +"\t"+ cmd);

            while ((temp = br.readLine()) != null) result.append(temp).append("\n");

            // Wait for process to terminate
            try
            {
                proc.waitFor();
            }
            catch (InterruptedException e)
            {
                System.err.println("Process was interrupted");
            }

            // Note: proc.exitValue() returns the exit value.
            // (Use if required)

            br.close();
            br=null;
            proc=null;

            System.gc(); //pfui! aber was will man machen...

        }
        catch (IOException e) {
            System.err.print("runCommand: ");
            System.err.println(e);
            e.printStackTrace();
            System.exit(-1);
        }
        return result.toString();
    }







    static HashMap <String, String> listOfBlastHits = new HashMap<String, String>();
    static int skipped=0;



    //checks if allready on stack and adds otherwise
    static void addtostack(String blastmatch, String sequName)
    {
        if (listOfBlastHits.containsKey(blastmatch))
        {
            //System.err.println("skipping: "+blastmatch);
            skipped++;
            return; //cont. with next match
        }

        listOfBlastHits.put(blastmatch, sequName);
    }



    /*
    	static void getGrameneLink()
    	{
    		System.out.println("<html>");

    		Iterator it = listOfBlastHits.keySet().iterator();
    		String seqpos="", seqstart, seqend;
    		int matchnumber=0;

    		String iValue;
            while(it.hasNext())
       	    {
           	    iValue=(String)it.next();

    			//System.out.print(listOfBlastHits.get(iValue));

    			seqstart=(iValue.substring(1,iValue.lastIndexOf(":")));
    			seqend=(iValue.substring(iValue.lastIndexOf(":")+1,iValue.length()));


    //http://rice.plantbiology.msu.edu/cgi-bin/gbrowse/rice/?name=Chr1%3A1..20000
    			System.out.println("<a href=\"http://rice.plantbiology.msu.edu/cgi-bin/gbrowse/rice/?name=Chr2%3A"+ seqstart+".."+seqend+"\">"+matchnumber+"</a>");
    			matchnumber++;
    		}
    		System.out.println("</html>");
    		System.err.println("in:"+matchnumber);
    	}
    */







    static int getSequFromStackStoredPos2File()
    {
        //input files
        String path=opt_outpath+"/pri-u-miRNAs/";
        String genomicfile=opt_databasefile+".plain"; //plain database file        

        File dir = new File(path);
        if(!dir.exists()) {if (!dir.mkdir()) System.out.println("\nERROR generating directory "+dir);}
        
        
        Iterator it = listOfBlastHits.keySet().iterator();
        String seqpos="";
        int matchnumber=0;
        boolean RC=false;

        String iValue;
        String iText;

        int seqstart;
        int seqlen;
        byte[] buffer;
        String seq="";


        try
        {
            RandomAccessFile randomAccessFile =new RandomAccessFile(genomicfile, "r");

            while(it.hasNext())
            {
                iValue=(String)it.next();
                //System.err.println(iValue);

                seqstart=Integer.parseInt(iValue.substring(1,iValue.lastIndexOf(":")))-1;
                seqlen=Integer.parseInt(iValue.substring(iValue.lastIndexOf(":")+1,iValue.length())) -seqstart;

                //add some nts of the genomic sequence to the prediction input
                seqstart-=opt_fiveprimeExtension;
                seqlen+=opt_threeprimeExtension+opt_fiveprimeExtension;
                if (seqstart<0) seqstart=0;

                randomAccessFile.seek(seqstart);
                buffer = new byte[seqlen];
                randomAccessFile.read(buffer);

                seq=new String(buffer);


                iText=listOfBlastHits.get(iValue);
                if(iValue.charAt(0)=='-')
                {
                    iText+=" RC";

                    seq=seq.replaceAll("A", "X");
                    seq=seq.replaceAll("T", "A");
                    seq=seq.replaceAll("X", "T");

                    seq=seq.replaceAll("G", "X");
                    seq=seq.replaceAll("C", "G");
                    seq=seq.replaceAll("X", "C");

                    seq= new StringBuffer(seq).reverse().toString();
                }

                Writer output = new BufferedWriter(new FileWriter(path+"/pri-u-miRNA"+"_"+(matchnumber)+".fasta"));
                output.write(iText);
                output.write("\n");
                output.write(seq);
                output.close();

                matchnumber++;
            }
            
            System.err.print(" (found "+ matchnumber +", skipped: "+skipped+") ");
            return matchnumber;

        }
        catch (IOException e)
        {
            System.out.println("\nERROR: IOException:");
            e.printStackTrace();
        }
        return 0;
    }




    static void collectResults()
    {
        String from=opt_outpath+"classification/";
        String outfile=opt_outpath+"results.csv";
        
        //check for splicing results
        Stack<String> resultHits=new Stack<String>();
        findFiles(new File(from), "-pos.", "", resultHits);

        int total=0;
        StringBuilder result=new StringBuilder();

        result.append("SplamiR output\nFolder & Filename\t5' Arm 5' End\t5' Arm 3' End\t3' Arm 5' End\t3' Arm 3' End\tLength in DB\tBLAST DB Score\tPri-5' End\tPri-3' End\tBLAST Target Score\tDirection\tIntron Start\tIntron End\tMiR-abela Stem Start\tMiR-abela Stem End\tScore\tLength\tEnergy\tSequence\tStructure\n");

        String filename, line;
        while(!resultHits.empty())
        {
            filename=resultHits.pop();

            try
            {
                BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
                while ((line =  br.readLine()) != null)
                {
                    total++;

                    line=line.replaceAll("-\\[0:0\\]-P", "splice=none:none-P");

                    // Compile the patten.
                    Pattern p = Pattern.compile("class=\"center[0-9]*\">([0-9]+)-([0-9]+):([0-9]+)-([0-9]+).*DB-len=([0-9]+)DB-e-value=(.*?)\\[([0-9]+):([0-9]+)\\]target-e-value=([0-9eE\\.-]*)([RC]*)splice=(.+):(.+)-.*?<\\/td.*?chr\\|.*?\\|([0-9]+)\\|([0-9]+)\\<.*?ter.*?\"\\>(.*?)\\<.*?ter.*?\"\\>(.*?)\\<.*?ter.*?\"\\>(.*?)\\<.*?fold\"\\>(.*?)\\<.*?\\<br\\>(.*?)\\<");
                    // Match it.
                    Matcher m = p.matcher(line);

                    // Get all matches.
                    while (m.find() == true)
                    {
                        result.append(filename);
                        //System.out.println("a "+m.group());
                        for (int ki=1; ki<=m.groupCount(); ki++)
                        {
                            result.append("\t" + m.group(ki) );
                        }
                        result.append("\n");
                    }

                }
                br.close();
            }
            catch (IOException e)
            {
                System.err.println("\nERROR: Unable to read input file");
                e.printStackTrace();
            }


            //	write output file
            try
            {
                File file = new File(outfile);
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                writer.append(result);
                writer.flush();
                writer.close();
            }
            catch (IOException e)
            {
                System.err.println("\nERROR: Unable to write output to file");
                e.printStackTrace();
            }


        }

        //give some information
        if (total==0)
        {
            System.out.println("\tNo candidates detected.");
            System.out.println("\nFinished.\n");            

            //	write output file
            try
            {
                File file = new File(outfile);
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                writer.append("No candidates detected.");
                writer.flush();
                writer.close();
            }
            catch (IOException e)
            {
                System.err.println("\nERROR: Unable to write output to file");
                e.printStackTrace();
            }
        }
        else
        {
            System.out.println("\n"+total+" candidate(s) detected. Results are stored in "+outfile);
        }

    }




    /*
     *  check for blast, etc.
     */
    private static void integrityCheck()
    {
        //check if all tools are present
        if (!new File("GeneSplicer/bin/linux/genesplicer").isFile())
        {
            System.out.println("ERROR: genesplicer is missing. Wrong directory?");
            printUsage();
            System.exit(2);
        }
        if (!new File("GeneSplicer/"+opt_genesplicerdata).isDirectory())
        {
            System.out.println("ERROR: GeneSplicer training set is missing. Wrong directory?");
            printUsage();
            System.exit(2);
        }
        if (!new File("RNAblast/blastallrna").isFile())
        {
            System.out.println("ERROR: File RNAblast/blastallrna is missing. Wrong directory?");
            printUsage();
            System.exit(2);
        }
    }


}
