/********************************************************************************************************
 * QRNA - Comparative analysis of biological sequences 
 *         with pair hidden Markov models, pair stochastic context-free
 *        grammars, and probabilistic evolutionary  models.
 *       
 * Version 2.0.0 (JUN 2003)
 *
 * Copyright (C) 2000-2003 Howard Hughes Medical Institute/Washington University School of Medicine
 * All Rights Reserved
 * 
 *     This source code is distributed under the terms of the
 *     GNU General Public License. See the files COPYING and LICENSE
 *     for details.
 ***********************************************************************************************************/

/* shuffle.c
 *
 * E. Rivas [St. Louis]
 * 
 * 9 april 1999.
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>

#include "funcs.h"
#include "evolfuncs.h"
#include "globals.h"
#include "squid.h"
#include "structs.h"
#include "version.h"


static void shuffle_2_sequences (FILE *ofp, char *outfile, 
				 int format, int num_align,
				 SQINFO sqinfoX, char *seqX, int *isegX, int *iseqX, int *ctX,
				 SQINFO sqinfoY, char *seqY, int *isegY, int *iseqY, int *ctY,
				 long int Lmax, int Lw, long int maxlenhit, int minlenhit,
				 int window, int slide,		
				 int allow_pseudoknots, int alignment, int n_shuffles,
				 int shuffle, int sre_shuffle, int con_shuffle, 
				 int verbose);
static void shuffle_window(FILE *ofp, char *outfile, 
			   SQINFO sqinfoX, int *isegX, int *iseqX, 
			   SQINFO sqinfoY, int *isegY, int *iseqY, 
			   int Lw, int leg, int win, int shft, 
			   double id_ali, double id_win_mean, double id_win_sd, 
			   int alignment,
			   int shuffle, int sre_shuffle, int con_shuffle,
			   int verbose);


static char banner[] = "qrna -- scores an alignment with the 3 models";

static char usage[]  = "\
Usage: eqrna [-options] <input_file.q> \n\
where options are:\n\
   -A             : do an all-to-all comparison between the two input files\n\
   -a             : print alignment \n\
   -B             : sre_shuffle the alignment keeping the gap structure of the window\n\
   -b             : shuffle the alignment \n\
   -C             : con_shuffle the alignment shuffling conserved, mutated, and gap positions independently\n\
   -e <num>       : number of sequen skipped in second file (for multiple comparisons). default 0. \n\
   -h             : print short help and usage info\n\
   -k             : allow pseudoknots (not implemented)\n\
   -l <minlenhit> : change the minlenhit parameter (default 0)\n\
   -L <maxlenhit> : change the maxlenhit parameter (default provided by longuest sequence)\n\
   -N <num>       : number of shuffles. default 1. \n\
   -o <outfile>   : direct structure-annotated sequence to <outfile>\n\
   -v             : verbose debugging output\n\
   -w <num>       : scanning window (default is full length)\n\
   -x <num>       : slide positions (default is 50)\n\
   -y <num>       : grab n sequences at random from the second data file to compare to each one of the first file\n\
";

static struct opt_s OPTIONS[] = {
  { "-A",        TRUE,  sqdARG_NONE},
  { "-a",        TRUE,  sqdARG_NONE},
  { "-B",        TRUE,  sqdARG_NONE},
  { "-b",        TRUE,  sqdARG_NONE},
  { "-C",        TRUE,  sqdARG_NONE},
  { "-e",        TRUE,  sqdARG_STRING},
  { "-E",        TRUE,  sqdARG_STRING},
  { "-h",        TRUE,  sqdARG_NONE},
  { "-k",        TRUE,  sqdARG_NONE},
  { "-l",        TRUE,  sqdARG_STRING},
  { "-L",        TRUE,  sqdARG_STRING},
  { "-N",        TRUE,  sqdARG_STRING},
  { "-o",        TRUE,  sqdARG_STRING},
  { "-v",        TRUE,  sqdARG_NONE},
  { "-w",        TRUE,  sqdARG_STRING},
  { "-x",        TRUE,  sqdARG_STRING},
  { "-y",        TRUE,  sqdARG_STRING},
  { "--printq",  FALSE, sqdARG_STRING},
};

#define NOPTIONS (sizeof(OPTIONS) / sizeof(struct opt_s))

int
main(int argc, char **argv)
{
  SQFILE  *sqfp;	          /* open sequence file                                     */
  SQFILE  *sqfp_b;	          /* open sequence file                                     */
  SQINFO   sqinfoX;               /* info structures for seqX                               */
  SQINFO   sqinfoY;               /* info structures for seqY                               */
  char    *seqfile;               /* input sequence file                                    */
  char    *seqfile_b;             /* input sequence file                                    */
  char    *seqX;	          /* sequence X                                             */
  char    *seqY;	          /* sequence to compare                                    */
  int     *ctX;                   /* .ct notation for seqX's RNA structure (if any)         */
  int     *ctY;                   /* .ct notation for seqY's RNA structure (if any)         */
  int     *iseqX, *isegX;	  /* sequence X integer form (without and with gaps)        */
  int     *iseqY, *isegY;	  /* sequence Y integer form (without and with gaps)        */
  long int curr_Lmax, Lmax;       /* length of the max alignment                            */
  int      format;                /* format of seq file                                     */

  int      alignment;	          /* TRUE prints alignment                                                     */
  int      allow_pseudoknots;	  /* TRUE to logodds space                                                     */
  int      alltoall;	          /* TRUE all-to-all comparison between the two input files                    */
  int      ran;                   /* TRUE to pick a random seq from the second data file                       */
  int      rani = -1;             /* number of shuffles per sequence of file A if ran==TRUE                    */
  int      ranc;                  /* counter for the number of shuffles                                        */
  int      shuffle;               /* TRUE to shuffle alignment                                                 */
  int      sre_shuffle;           /* TRUE to sre_shuffle alignment                                             */
  int      con_shuffle;           /* TRUE to con_shuffle alignment                                             */
  int      verbose;               /* TRUE to be extremely verbose to debug                                     */

  char    *outfile;               /* where to send the output                               */
  FILE    *ofp;	                  /* open output file                                       */
  char    *optname;
  char    *optarg; 
  int      optind;	
  int      s, s_new, seed;
  int      num_seqs = 0;
  int      num = 0, skip;

  int      minlenhit = 0;         /* min length hit by default 0                                */
  long int maxlenhit = 0;         /* max length hit by default provided by the longer aligments */
  int      nseqs;                 /* total number of sequences                                  */
  int      nXseq = 0, nYseq = 0;
  int      num_ali = 0;
  int      slide, window, winop;
  int      Lw;
  int      n_shuffles = 1;

  /* re-seed the random number generator.
   */
  seed = (int) time ((time_t *) NULL);
  sre_srandom(seed); /* reinit sre_random each time you shuffle a sequence */

  /* Parse command line
   */
  alignment         = FALSE;  /* TRUE  ==  prints alignment                                              */
  allow_pseudoknots = FALSE;  /* TRUE  ==  allow pseudoknots                                             */
  alltoall          = FALSE;  /* TRUE  ==  all-to-all comparison                                         */
  ran               = FALSE;  /* TRUE  ==  pick a random seq from the second file                        */
  shuffle           = FALSE;  /* TRUE  ==  shuffle alignment                                             */
  sre_shuffle       = FALSE;  /* TRUE  ==  sre_shuffle alignment                                         */
  con_shuffle       = FALSE;  /* TRUE  ==  con_shuffle alignment                                         */
  verbose           = FALSE;  /* TRUE  ==  for debuging                                                  */
  winop             = FALSE;  /* TRUE  ==  use a window; FALSE == use whole alignment                    */
  
  slide          = 50;
  skip           = 0;

  outfile        = NULL;
  seqfile        = NULL;
  seqfile_b      = NULL;
   
  while (Getopt(argc, argv, OPTIONS, NOPTIONS, usage,
		&optind, &optname, &optarg))
    {
      if      (strcmp(optname, "-A") == 0)   alltoall              = TRUE;
      else if (strcmp(optname, "-a") == 0)   alignment             = TRUE;
      else if (strcmp(optname, "-B") == 0)   sre_shuffle           = TRUE;
      else if (strcmp(optname, "-b") == 0)   shuffle               = TRUE;
      else if (strcmp(optname, "-C") == 0)   con_shuffle           = TRUE;
      else if (strcmp(optname, "-e") == 0)   skip                  = atoi(optarg);
      else if (strcmp(optname, "-k") == 0)   allow_pseudoknots     = TRUE;
      else if (strcmp(optname, "-l") == 0)   minlenhit             = atoi(optarg);
      else if (strcmp(optname, "-L") == 0)   maxlenhit             = atoi(optarg);
      else if (strcmp(optname, "-N") == 0)   n_shuffles            = atoi(optarg);
      else if (strcmp(optname, "-o") == 0)   outfile               = optarg;
      else if (strcmp(optname, "-v") == 0)   verbose               = TRUE;
      else if (strcmp(optname, "-w") == 0) { window                = atoi(optarg); winop = TRUE; }
      else if (strcmp(optname, "-x") == 0)   slide                 = atoi(optarg);
      else if (strcmp(optname, "-y") == 0)   rani                  = atoi(optarg);
      else if (strcmp(optname, "-h")        == 0) 
	{
	  puts(banner);
	  printf("          %s (%s)", RELEASE, RELEASEDATE);
	  printf(" using squid %s (%s)\n", squid_version, squid_date);
	  puts(usage);
	  exit(0);
	}
    }
  
  if (argc - optind == 1) {
    seqfile  = argv[optind]; 
  }
  else if (argc - optind == 2) {
    seqfile   = argv[optind++]; 
    seqfile_b = argv[optind]; 
  }
  else {
    puts(banner);
    printf("version: %s (%s)\n", RELEASE, RELEASEDATE);
    Die("Incorrect number of command line arguments.\n%s \n\n", usage);
  }
  
  if (rani > 0) ran = TRUE;

  /* options incompatibilities
   */
  if (winop && window <= 0) Die("window has to be larger than zero\n");
  if (!winop) window = -1;

  if (seqfile == NULL) {
    puts(usage);
    exit(0);
  }
  
  /* Open output file 
   */
  ofp = stdout;
  if (outfile != NULL && (ofp = fopen(outfile, "w")) == NULL)
    Die("Failed to open output file %s", outfile);
  else outfile = "out";
  
  /* Open sequence file(s)
   */
  if (! SeqfileFormat(seqfile, &format, NULL))
    Die("Failed to determine format of sequence file %s\n", seqfile);     
  
  if (maxlenhit > 0) 
    {
      nseqs = 0;

      if (!winop) Lmax = maxlenhit;
      else        Lmax = (maxlenhit < window)? maxlenhit : window;
    }
  else 
    {
      /* determine maximum length for sequence file (Lmax)
       * (this is too expensive to do)
       */
      if (winop) 
	maxlenhit = BIGINT;
      else /* if no window given, limit the max length of aligments for memoery reasons */
	maxlenhit = 1000;
      
      if ((sqfp = SeqfileOpen(seqfile, format, NULL)) == NULL)
	Die("Failed to open sequence file %s", seqfile);
      CheckMaxLength(sqfp, format, &curr_Lmax, &nseqs, maxlenhit); 
      Lmax = curr_Lmax; 
      SeqfileClose(sqfp);
    }

  if ((sqfp = SeqfileOpen(seqfile, format, NULL)) == NULL)
    Die("Failed to open sequence file %s", seqfile);
  
  
  if(seqfile_b != NULL) {
    if (! SeqfileFormat(seqfile_b, &format, NULL))
      Die("Failed to determine format of sequence file %s\n", seqfile_b);
    
    if (nseqs > 0) {
      /* determine maximum length for sequence file (Lmax)
       *
       */
      if ((sqfp_b = SeqfileOpen(seqfile_b, format, NULL)) == NULL)
	Die("Failed to open sequence file %s", seqfile_b);
      CheckMaxLength(sqfp_b, format, &curr_Lmax, &nseqs, maxlenhit);
      if (curr_Lmax > Lmax) Lmax = curr_Lmax;
      SeqfileClose(sqfp_b);
    }
    
    if ((sqfp_b = SeqfileOpen(seqfile_b, format, NULL)) == NULL)
      Die("Failed to open sequence file %s", seqfile_b);
  }

  if (alltoall && seqfile_b == NULL) {
    seqfile_b = seqfile;
    if ((sqfp_b = SeqfileOpen(seqfile_b, format, NULL)) == NULL)
      Die("Failed to open sequence file %s", seqfile_b);
  }
  
  /* Allocate space for iseg's, these arrays keep the full alignments
   */
  AllocIntSeqs(Lmax, &isegX, &isegY);
  
  /* Allocate space for arrays used in the calculation [iseq's, dpd, dpf, mx, sc->ardiag, sc->arfull]
   */
  Lw = (window > -1)? window : Lmax; /* window of calculation */
  AllocIntSeqs(2*Lw, &iseqX, &iseqY);


  if (ran) {
    if (seqfile_b == NULL) Die ("this ran version requires two files");
    while (ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY)) num_seqs++;
    FreeSequence(seqY, &sqinfoY);  
  }
  else {
    while (seqfile_b != NULL && num++ < skip) {
      ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY);
      FreeSequence(seqY, &sqinfoY);  
    }
  }
  
  /* Read seqX (sequence may have gaps)
   */
  while (ReadGapSeq(sqfp, format, &seqX, &sqinfoX))
    {
      nXseq++;
      /* Read seqY (sequence may have gaps)
       */
      if (alltoall) 
	{
	  while (ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY)) { 
	    nYseq++;
	    num_ali++;
	    shuffle_2_sequences(ofp, outfile, format, num_ali,
				sqinfoX, seqX, isegX, iseqX, ctX,
				sqinfoY, seqY, isegY, iseqY, ctY,
				Lmax, Lw, maxlenhit, minlenhit,
				window, slide,
				allow_pseudoknots, alignment,  n_shuffles,
				shuffle, sre_shuffle, con_shuffle, 
				verbose);
	    FreeSequence(seqY, &sqinfoY); 
	  }
	  /* reopen the sqfp_b file to go over it with the next motif
	   */
	  SeqfileClose(sqfp_b);
	  nYseq = 0;
	  if ((sqfp_b = SeqfileOpen(seqfile_b, format, NULL)) == NULL)
	    Die("Failed to open sequence file %s", seqfile_b);
	  if (seqfile_b == seqfile)     
	    while (nYseq++ < nXseq) {
	      ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY);
	      FreeSequence(seqY, &sqinfoY); 
	    }
	}
      else if (ran) {
	/* reopen the sqfp_b file to go over it with the next motif
	 */
	ranc = 0;
	s_new = (int)(sre_random()*num_seqs);
	
	while (ranc < rani) {
	  
	  ranc ++;
	  s = s_new;
	  
	  SeqfileClose(sqfp_b);
	  if ((sqfp_b = SeqfileOpen(seqfile_b, format, NULL)) == NULL)
	    Die("Failed to open sequence file %s", seqfile_b);
	  
	  
	  num = 0;
	  while (seqfile_b != NULL && num++ < s) {
	    ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY);
	    FreeSequence(seqY, &sqinfoY);  
	  }
	  ReadGapSeq(sqfp_b, format, &seqY, &sqinfoY);
	  
	  shuffle_2_sequences(ofp, outfile, format, num_ali,
			      sqinfoX, seqX, isegX, iseqX, ctX,
			      sqinfoY, seqY, isegY, iseqY, ctY,
			      Lmax, Lw, maxlenhit, minlenhit,
			      window, slide,
			      allow_pseudoknots, alignment,  n_shuffles,
			      shuffle, sre_shuffle, con_shuffle, 
			      verbose);
	  
	  FreeSequence(seqY, &sqinfoY); 
	  
	  while (s_new == s) 
	    s_new = (int)(sre_random()*num_seqs);
	  
	}
	
      }
      else if (ReadGapSeq((seqfile_b == NULL)? sqfp:sqfp_b, format, &seqY, &sqinfoY)) 
	{ 
	  nYseq++;
	  
	  if (nXseq != nYseq) 
	    Die("seqs %c and %c are not in sync", sqinfoX.name, sqinfoY.name);
	  
	  shuffle_2_sequences(ofp, outfile, format, num_ali,
			      sqinfoX, seqX, isegX, iseqX, ctX,
			      sqinfoY, seqY, isegY, iseqY, ctY,
			      Lmax, Lw, maxlenhit, minlenhit,
			      window, slide,
			      allow_pseudoknots, alignment,  n_shuffles,
			      shuffle, sre_shuffle, con_shuffle, 
			      verbose);
	  
	  FreeSequence(seqY, &sqinfoY);  
	}
      FreeSequence(seqX, &sqinfoX);    
      
    }

  /* Cleanup */
  if (outfile        != NULL) fclose(ofp); 
  if (seqfile        != NULL) SeqfileClose(sqfp); 
  if (seqfile_b      != NULL) SeqfileClose(sqfp_b); 
  
  free(isegX); 
  free(isegY); 
  free(iseqX); 
  free(iseqY);  
  
   return EXIT_SUCCESS;
}


void
shuffle_2_sequences (FILE *ofp,  char *outfile, 
		     int format, int num_align,
		     SQINFO sqinfoX, char *seqX, int *isegX, int *iseqX, int *ctX,
		     SQINFO sqinfoY, char *seqY, int *isegY, int *iseqY, int *ctY,
		     long int Lmax, int Lw, long int maxlenhit, int minlenhit,
		     int window, int slide,		
		     int allow_pseudoknots, int alignment, int n_shuffles,
		     int shuffle, int sre_shuffle, int con_shuffle,
		     int verbose)
{
  char                      *aliss;
  int                        win;
  int                        leg;
  int                        shft;
  double                     id;
  double                     mut;
  double                     gap;
  double                     id_win_mean;
  double                     id_win_sd;
  int                        shuffles = 0;
 
  if (minlenhit >= maxlenhit) Die ("You want alignments with positive length, right?\n");
  if ((sqinfoX.len > maxlenhit || sqinfoY.len > maxlenhit)) {
    Warn("Too long ++ skip hit # %d\n>%s (%d)\n>%s (%d)\n", num_align, sqinfoX.name, sqinfoX.len, 
	 sqinfoY.name, sqinfoY.len);
    return;
  }
  if ((sqinfoX.len < minlenhit || sqinfoY.len < minlenhit)) {
    Warn("Too short ++ skip hit # %d\n>%s (%d)\n>%s (%d)\n", num_align, sqinfoX.name, sqinfoX.len, 
	 sqinfoY.name, sqinfoY.len);
    return;
  }

  /* Create arrays with given aligment:
   *    isegX[sqinfoX->len]         
   *    isegY[sqinfoY->len]    (int seqs with gaps) 
   */
  FormatSeqs(ofp, Lmax, format, seqX, seqY, &sqinfoX, &sqinfoY, &ctX, &ctY, isegX, isegY, 
	     allow_pseudoknots, verbose);
  
  /* (0) leg = minimum length of aligment 
   *
   * Function RemoveJointGaps() can be passed to ScoreWithModels() in "scorewithmodels.c" if 
   * one wants to remove the common gaps of the two alignments window by window.
   * The advantage of that is that you keep a common coordinate sistem,
   * the disadvantage is that the "actual" window used may be smaller than
   * the given one.
   *
   * RemoveJointGaps() modifies both sqinfoX.ss and sqinfoY.ss, as well as isegX and isegY
   */
  RemoveJointGaps(sqinfoX, isegX, sqinfoY, isegY, &leg, FALSE, aliss);

  if (window != -1 && verbose) {
    fprintf(ofp, "length of whole alignment after removing common gaps: %d \n", leg); 
  }

  if (window == -1) { win = leg;    shft = leg;   }
  else              { win = window; shft = slide; }
  
  

  /* Percentage ID, GAP and MUT of the aligment */
  PercIdSeqs(isegX, isegY, leg-1, leg-1, &id, &gap, &mut);
  AliIdStats(isegX, isegY, leg-1, leg-1, win, shft, &id_win_mean, &id_win_sd);
  if (verbose) printf("ALI id %f id_win_mean %f id_win_st %f\n", id, id_win_mean, id_win_sd);

  if (verbose) fprintf(ofp, "[alignment ID = %.2f MUT = %.2f GAP = %.2f]\n\n", id, mut, gap); 
  if (verbose) fprintf(ofp, "Lw %d leg %d win %d sft %d\n", Lw, leg, win, shft);
  
  while (shuffles < n_shuffles) {
    shuffle_window(ofp, outfile, 
		   sqinfoX, isegX, iseqX, 
		   sqinfoY, isegY, iseqY,
		   Lw, leg, win, shft, 
		   id, id_win_mean, id_win_sd,
		   alignment,
		   shuffle, sre_shuffle, con_shuffle, 
		   verbose);
    
    shuffles ++; 
  }

  if (sqinfoY.flags & SQINFO_SS) free(ctY); 
  if (sqinfoX.flags & SQINFO_SS) free(ctX);
}

void
shuffle_window(FILE *ofp, char *outfile,
	       SQINFO sqinfoX, int *isegX, int *iseqX, 
	       SQINFO sqinfoY, int *isegY, int *iseqY,
	       int Lw, int leg, int win, int shft, 
	       double id_ali, double id_win_mean, double id_win_sd,
	       int alignment,
	       int shuffle, int sre_shuffle, int con_shuffle,
	       int verbose)
{
  int                 pos;
  int                 dis;
  int                 slide;
  int                 start;
  int                 startX, endX;        /* first and last position of analysis for seqX   */
  int                 startY, endY;        /* first and last position of analysis for seqY   */
  int                 lenX, lenY;          /* len of seq's  without gaps                     */
  int                 fstX, fstY;          /* mapping of startX and startY to the seq without gaps */
  int                *iseqshX, *iseqshY;
  int                *seqX,    *seqY;
  double             *freqX,   *freqY;
  double              id, gap, mut;

  slide = shft;

  pos = 0;

  while (pos < leg) {
    
    dis = (pos<leg-win)? win : leg-pos;

    PercIdSeqs(isegX+pos, isegY+pos, dis-1, dis-1, &id, &gap, &mut);
    start = pos;
    win = dis;
    
    lenX = win;
    lenY = win; 
    
    startX = start;
    startY = start;
    
    endX = startX + lenX - 1;
    endY = startY + lenY - 1;
    
    if (verbose) fprintf(ofp, "start %d win %d\n", start, win);

    /* if (shuffle == TRUE) shuffle aligment */
    if (shuffle || sre_shuffle || con_shuffle) {
      AllocIntSeqs(win, &iseqshX, &iseqshY);
      DupIntSeq(isegX, iseqshX, startX+win-1, win-1);
      DupIntSeq(isegY, iseqshY, startY+win-1, win-1);  
      
      if (shuffle)     Shuffle2IntSequences(iseqshX, iseqshY, win, win-1, win-1, verbose);
      if (sre_shuffle) QRNAIntShuffle(iseqshX, iseqshY, win);
      if (con_shuffle) QRNAIntConservedShuffle(iseqshX, iseqshY, win);
      
      seqX = iseqshX;
      seqY = iseqshY;
    }
    else {
      seqX = isegX+startX;
      seqY = isegY+startY;
    }
    
    PercIdSeqs(seqX, seqY, win-1, win-1, &id, &gap, &mut);
    if (verbose) fprintf(ofp, "window: ID = %.2f MUT = %.2f GAP = %.2f\n\n", id, mut, gap); 

    PrintQfile(ofp, outfile, sqinfoX, seqX, sqinfoY, seqY, 0, win, start);
    
    /* (1) duplicate the region (start, start+win-1) of iseg into iseq. 
     *     Remove the gaps, and calculate lenX, and lenY.
     */
    DupIntSeq(seqX, iseqX, win-1, win-1);
    DupIntSeq(seqY, iseqY, win-1, win-1);  
    
    RemoveGaps(iseqX, win, &lenX, verbose); /* len of seqX without gaps */
    RemoveGaps(iseqY, win, &lenY, verbose); /* len of seqY without gaps */
    
    fstX = PosNoGaps(isegX, startX);
    fstY = PosNoGaps(isegY, startY);
    
    if (verbose) {
      fprintf(ofp, "length alignment: %d (id=%.2f) (mut=%.2f) (gap=%.2f)", win, id, mut, gap);
    if      (shuffle)     fprintf(ofp, "(shuffled)\n");
    else if (sre_shuffle) fprintf(ofp, "(sre_shuffled)\n");
    else if (con_shuffle) fprintf(ofp, "(con_shuffled)\n");
    else                  fprintf(ofp, "\n");
    
    BaseComp(ofp, iseqX, lenX-1, lenX-1, freqX);
    BaseComp(ofp, iseqY, lenY-1, lenY-1, freqY);
    
    fprintf(ofp, "posX: %d-%d [%d-%d](%d) -- (%.2f %.2f %.2f %.2f) \n", 
	    startX, endX, fstX, fstX+lenX-1, lenX, freqX[0], freqX[1], freqX[2], freqX[3]);
    fprintf(ofp, "posY: %d-%d [%d-%d](%d) -- (%.2f %.2f %.2f %.2f) \n", 
	    startY, endY, fstY, fstY+lenY-1, lenY, freqY[0], freqY[1], freqY[2], freqY[3]);
  }
    
    if (shuffle) {
      free(iseqshX);
      free(iseqshY);
    }

     pos = (pos<leg-win)? pos+slide : leg;

  }
}
