static char rcsid[] = "$Id: d32d7d3f276e26e05028be22119eb95488f6e726 $";
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_MEMCPY
#define memcpy(d,s,n) bcopy((s),(d),(n))
#endif
#ifndef HAVE_MEMMOVE
#define memmove(d,s,n) bcopy((s),(d),(n))
#endif

#include "stage1hr.h"
#include "stage1hr-single.h"
#include "stage1hr-paired.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>		/* For rint */

#include "assert.h"
#include "mem.h"
#include "types.h"		/* Needed for HAVE_64_BIT */
#include "univcoord.h"

#include "list.h"
#include "compress.h"
#include "record.h"

#include "genomebits_mismatches.h" /* For MISMATCH_EXTRA */

#include "stage1hr.h"
#include "kmer-search.h"
#include "extension-search.h"
#include "segment-search.h"
#include "stage1hr-single.h"
#include "transcriptome-search.h"
#include "tr-extension-search.h"

#include "concordance.h"
#include "path-solve.h"
#include "path-fusion.h"

#include "transcript-remap.h"
#include "transcript-velocity.h"
#include "path-eval.h"
#include "pathpair-eval.h"

#include "orderstat.h"


/* #define MIN_SIZELIMIT 100 */

#define MAX_SINGLE_END_HITS 1000
#define MAX_UNEXTENDED_HITS 1000


#ifdef DEBUG0
#define debug0(x) x
#else
#define debug0(x)
#endif

#ifdef DEBUG
#define debug(x) x
#else
#define debug(x)
#endif

/* determine_pairtype */
#ifdef DEBUG14
#define debug14(x) x
#else
#define debug14(x)
#endif

/* consolidate_paired_results */
#ifdef DEBUG16
#define debug16(x) x
#else
#define debug16(x)
#endif


static Mode_T mode;
static int index1part;
static int index1interval;
static int index1part_tr;

static Transcriptome_T transcriptome;
static bool genome_align_p;
static bool transcriptome_align_p;

static double defect_rate = 0.01;

static double user_nmismatches_filter_float;
static double user_mincoverage_filter_float;

static double max_middle_insertions_float;
static double max_middle_deletions_float;

static Chrpos_T shortsplicedist;
static Chrpos_T shortsplicedist_novelend;

static bool splicingp;
static int maxpaths_search;	/* Not currently used */
static int maxpaths_report;	/* Not currently used */

static bool *circularp;
static int pairmax_linear;
static int pairmax_circular;


#define T Stage1_T


static void
single_read_transcriptome_search (int *found_score, bool *found_transcriptp, Method_T *last_method,
				  T this, Knownsplicing_T knownsplicing,
				  Shortread_T queryseq, int querylength,
				  int *mismatch_positions_alloc,
				  Compress_T query_compress_fwd, Compress_T query_compress_rev,
				  int max_insertionlen, int max_deletionlen, int nmismatches_allowed,
				  Trdiagpool_T trdiagpool, Intlistpool_T intlistpool, Uintlistpool_T uintlistpool,
				  Univcoordlistpool_T univcoordlistpool, Listpool_T listpool, 
				  Trpathpool_T trpathpool, Pathpool_T pathpool, Transcriptpool_T transcriptpool,
				  Hitlistpool_T hitlistpool, bool first_read_p) {

  bool tr_found_transcriptp = false;

  debug(printf("Entered single_read_transcriptome_search\n"));

  if (*last_method < TR__TR_EXACT) {
    Stage1_init_end_oligos_tr(this,querylength);
    Stage1_init_end_positions_tr(this,querylength);

    debug(printf("Read %s: Running Transcriptome_search_exact\n",first_read_p ? "5'" : "3'"));
    Transcriptome_search_exact(&(*found_score),&tr_found_transcriptp,
			       &this->sense_trpaths,&this->antisense_trpaths,

			       this,querylength,query_compress_fwd,query_compress_rev,
			       intlistpool,uintlistpool,trpathpool,hitlistpool,
			       /*method*/TR__TR_EXACT);
    *last_method = TR__TR_EXACT;
    debug(printf("After Transcriptome_search_exact, we have sense %d and antisense %d trpaths\n",
		 List_length(this->sense_trpaths),List_length(this->sense_trpaths)));

    if (tr_found_transcriptp == true) {
      Stage1_consolidate_paths(this,queryseq,query_compress_fwd,query_compress_rev,
			       uintlistpool,intlistpool,univcoordlistpool,listpool,
			       pathpool,transcriptpool,hitlistpool);
      debug(Stage1_list_paths(this));
      *found_transcriptp = true;
      return;
    }
  }


  if (*last_method < TR__TR_EXT) {
    Stage1_fill_all_oligos_tr(this,querylength);

    debug(printf("Read %s: Running Tr_extension_search\n",first_read_p ? "5'" : "3'"));
    Tr_extension_search(&(*found_score),&tr_found_transcriptp,
			&this->sense_trpaths,&this->antisense_trpaths,

			this,querylength,mismatch_positions_alloc,
			query_compress_fwd,query_compress_rev, 

			trdiagpool,intlistpool,uintlistpool,listpool,
			trpathpool,pathpool,hitlistpool,
			max_insertionlen,max_deletionlen,nmismatches_allowed,
			/*genestrand*/0,/*method*/TR__TR_EXT);
    *last_method = TR__TR_EXT;
    debug(printf("After Tr_extension_search, we have sense %d and antisense %d trpaths\n",
		 List_length(this->sense_trpaths),List_length(this->antisense_trpaths)));

    if (tr_found_transcriptp == true) {
      Stage1_consolidate_paths(this,queryseq,query_compress_fwd,query_compress_rev,
			       uintlistpool,intlistpool,univcoordlistpool,listpool,
			       pathpool,transcriptpool,hitlistpool);
      debug(Stage1_list_paths(this));
      *found_transcriptp = true;
      return;
    }
  }


  if (*last_method < TR__TR_COMPLETE) {
    debug(printf("Read %s: Running Transcriptome_search\n",first_read_p ? "5'" : "3'"));
    Transcriptome_search_complete(&(*found_score),&tr_found_transcriptp,
				  &this->sense_trpaths,&this->antisense_trpaths,
				  
				  this,querylength,this->indelinfo,this->mergeinfo_tr,
				  this->tplus_stream_array,this->tplus_streamsize_array,this->tplus_diagterm_array,
				  this->tminus_stream_array,this->tminus_streamsize_array,this->tminus_diagterm_array,
				  
				  mismatch_positions_alloc,query_compress_fwd,query_compress_rev,
				  max_insertionlen,max_deletionlen,
				  intlistpool,uintlistpool,listpool,
				  trpathpool,pathpool,hitlistpool,/*method*/TR__TR_COMPLETE);
    *last_method = TR__TR_COMPLETE;
    debug(printf("After Transcriptome_search_complete, we have sense %d and antisense %d trpaths\n",
		 List_length(this->sense_trpaths),List_length(this->antisense_trpaths)));

    if (tr_found_transcriptp == true) {
      Stage1_consolidate_paths(this,queryseq,query_compress_fwd,query_compress_rev,
			       uintlistpool,intlistpool,univcoordlistpool,listpool,
			       pathpool,transcriptpool,hitlistpool);
      debug(Stage1_list_paths(this));
      *found_transcriptp = true;
      return;
    }
  }


  if (*last_method < TR__TR_APPROX) {
    debug(printf("Read %s: Running Transcriptome_search_approx\n",first_read_p ? "5'" : "3'"));
    Transcriptome_search_approx(&(*found_score),&tr_found_transcriptp,
				&this->sense_trpaths,&this->antisense_trpaths,
				
				this,querylength,query_compress_fwd,query_compress_rev,
				max_insertionlen,max_deletionlen,
				intlistpool,uintlistpool,listpool,
				trpathpool,pathpool,hitlistpool,/*method*/TR__TR_APPROX);
    *last_method = TR__TR_APPROX;
    debug(printf("After Transcriptome_search_approx, we have sense %d and antisense %d trpaths\n",
		 List_length(this->sense_trpaths),List_length(this->antisense_trpaths)));

    if (tr_found_transcriptp == true) {
      Stage1_consolidate_paths(this,queryseq,query_compress_fwd,query_compress_rev,
			       uintlistpool,intlistpool,univcoordlistpool,listpool,
			       pathpool,transcriptpool,hitlistpool);
      debug(Stage1_list_paths(this));
      *found_transcriptp = true;
      return;
    }
  }

  Stage1_solve_unsolved_paths(&(*found_score),this,
				max_insertionlen,max_deletionlen,
				query_compress_fwd,query_compress_rev,
				queryseq,querylength,knownsplicing,
				uintlistpool,intlistpool,univcoordlistpool,listpool,pathpool,
				transcriptpool,hitlistpool);

  Stage1_consolidate_paths(this,queryseq,query_compress_fwd,query_compress_rev,
			   uintlistpool,intlistpool,univcoordlistpool,listpool,
			   pathpool,transcriptpool,hitlistpool);

  debug(Stage1_list_paths(this));
  return;
}



static List_T
paired_search (int *found_score_paired, int *found_score_5, int *found_score_3,
	       bool *found_transcriptp_5, bool *found_transcriptp_3,
	       Method_T *last_method_5, Method_T *last_method_3,

	       List_T *unextended_sense_seg2paths5_gplus,
	       List_T *unextended_sense_seg2paths5_gminus,
	       List_T *unextended_sense_seg2paths3_gplus,
	       List_T *unextended_sense_seg2paths3_gminus,
	       List_T *unextended_antisense_seg2paths5_gplus,
	       List_T *unextended_antisense_seg2paths5_gminus,
	       List_T *unextended_antisense_seg2paths3_gplus,
	       List_T *unextended_antisense_seg2paths3_gminus,

	       List_T *sense_seg2paths5_gplus,
	       List_T *sense_seg2paths5_gminus,
	       List_T *sense_seg2paths3_gplus,
	       List_T *sense_seg2paths3_gminus,
	       List_T *antisense_seg2paths5_gplus,
	       List_T *antisense_seg2paths5_gminus,
	       List_T *antisense_seg2paths3_gplus,
	       List_T *antisense_seg2paths3_gminus,

	       List_T pathpairs, T this5, T this3, EF64_T repetitive_ef64,

	       Shortread_T queryseq5, Shortread_T queryseq3,
	       char *queryuc_ptr_5, char *queryrc5, int querylength5,
	       char *queryuc_ptr_3, char *queryrc3, int querylength3,
	       Knownsplicing_T knownsplicing, Knownindels_T knownindels,
			
	       int *mismatch_positions_alloc_5, int *mismatch_positions_alloc_3,
	       Univcoord_T *novel_diagonals_alloc, unsigned short *localdb_alloc,
	       Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
	       Compress_T query3_compress_fwd, Compress_T query3_compress_rev,
			    
	       int nmismatches_allowed_5, int nmismatches_allowed_3,
	       int max_insertionlen_5, int max_insertionlen_3, int max_deletionlen_5, int max_deletionlen_3,
	       int genestrand, Chrpos_T pairmax_linear, Chrpos_T overall_max_distance_5, Chrpos_T overall_max_distance_3,
	       Chrpos_T overall_end_distance_5, Chrpos_T overall_end_distance_3,
			      
	       Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
	       Listpool_T listpool, Univdiagpool_T univdiagpool,
	       Pathpool_T pathpool, Transcriptpool_T transcriptpool,
	       Vectorpool_T vectorpool, Hitlistpool_T hitlistpool,
	       Spliceendsgen_T spliceendsgen5, Spliceendsgen_T spliceendsgen3, Pass_T pass,
	       int sufficient_score_5, int sufficient_score_3, bool use_unextended_p) {

  Univcoord_T *gplus5_diagonals, *gminus5_diagonals, *gplus3_diagonals, *gminus3_diagonals;
  int gplus5_ndiagonals, gminus5_ndiagonals, gplus3_ndiagonals, gminus3_ndiagonals;

  /* For Segment_search */
  struct Record_T *plus_records5 = NULL, *minus_records5 = NULL, *plus_records3 = NULL, *minus_records3 = NULL;
  int plus_nrecords5 = 0, minus_nrecords5 = 0, plus_nrecords3 = 0, minus_nrecords3 = 0;

  if (use_unextended_p == true ||
      (*found_score_5 > sufficient_score_5 || *found_transcriptp_5 == false ||
       (*found_score_3 <= sufficient_score_3 && *found_transcriptp_3 == true))) {
    /* Sense */
    if (use_unextended_p == true) {
      gplus3_diagonals = Path_genomiclows(&gplus3_ndiagonals,this3->unextended_sense_paths_gplus);
      gminus3_diagonals = Path_genomichighs(&gminus3_ndiagonals,this3->unextended_sense_paths_gminus);
    } else {
      gplus3_diagonals = Path_genomiclows(&gplus3_ndiagonals,this3->sense_paths_gplus);
      gminus3_diagonals = Path_genomichighs(&gminus3_ndiagonals,this3->sense_paths_gminus);
    }

    if (this5->all_oligos_gen_filledp == false) {
      Stage1_fill_all_oligos_gen(this5,querylength5,genestrand);
    }
    if (this5->all_positions_gen_filledp == false) {
      Stage1_fill_all_positions_gen(this5,querylength5,genestrand);
    }

    debug(printf("Calling Segment_identify_lower to find sense plus records5 against 3' diagonals\n"));
    plus_records5 = Segment_identify_lower(&plus_nrecords5,
#ifdef LARGE_GENOMES
					   this5->plus_positions_high,
#endif
					   this5->plus_positions,this5->plus_npositions,this5->validp,
					   this5->forward_oligos,repetitive_ef64,

					   this5->streamptr_alloc,this5->streamsize_alloc,
					   this5->querypos_diagterm_alloc,this5->mergeinfo,
					   /*max_pairlength*/pairmax_linear,overall_max_distance_5,querylength5,
					   gplus3_diagonals,gplus3_ndiagonals,/*plusp*/true);
    
    debug(printf("Calling Segment_identify_higher to find sense minus records5 against 3' diagonals\n"));
    minus_records5 = Segment_identify_higher(&minus_nrecords5,
#ifdef LARGE_GENOMES
					     this5->minus_positions_high,
#endif
					     this5->minus_positions,this5->minus_npositions,this5->validp,
					     this5->revcomp_oligos,repetitive_ef64,

					     this5->streamptr_alloc,this5->streamsize_alloc,
					     this5->querypos_diagterm_alloc,this5->mergeinfo,
					     /*max_pairlength*/pairmax_linear,overall_max_distance_5,querylength5,
					     gminus3_diagonals,gminus3_ndiagonals,/*plusp*/false);
    FREE(gminus3_diagonals);
    FREE(gplus3_diagonals);
    debug(printf("3' sense diagonals %d and %d => 5' records %d plus and %d minus\n",
		 gplus3_ndiagonals,gminus3_ndiagonals,plus_nrecords5,minus_nrecords5));
    
    Segment_search_all(&(*found_score_5),&(*found_transcriptp_5),

		       &(*unextended_sense_seg2paths5_gplus),&(*unextended_sense_seg2paths5_gminus),
		       &(*unextended_antisense_seg2paths5_gplus),&(*unextended_antisense_seg2paths5_gminus),

		       &(*sense_seg2paths5_gplus),&(*sense_seg2paths5_gminus),
		       &(*antisense_seg2paths5_gplus),&(*antisense_seg2paths5_gminus),
		       plus_records5,plus_nrecords5,minus_records5,minus_nrecords5,

		       queryseq5,queryuc_ptr_5,queryrc5,querylength5,mismatch_positions_alloc_5,
		       novel_diagonals_alloc,localdb_alloc,
		       this5,knownsplicing,knownindels,
		       query5_compress_fwd,query5_compress_rev,
		       max_insertionlen_5,max_deletionlen_5,nmismatches_allowed_5,
		       overall_max_distance_5,overall_end_distance_5,
		       genestrand,/*paired_end_p*/true,/*first_read_p*/true,
		       univdiagpool,intlistpool,uintlistpool,univcoordlistpool,listpool,
		       pathpool,transcriptpool,vectorpool,hitlistpool,spliceendsgen5,
		       /*method*/SEGMENT2,pass);
    FREE(plus_records5); FREE(minus_records5);


    if (splicingp == true) {
      /* Antisense */
      if (use_unextended_p == true) {
	gplus3_diagonals = Path_genomiclows(&gplus3_ndiagonals,this3->unextended_antisense_paths_gplus);
	gminus3_diagonals = Path_genomichighs(&gminus3_ndiagonals,this3->unextended_antisense_paths_gminus);
      } else {
	gplus3_diagonals = Path_genomiclows(&gplus3_ndiagonals,this3->antisense_paths_gplus);
	gminus3_diagonals = Path_genomichighs(&gminus3_ndiagonals,this3->antisense_paths_gminus);
      }

      debug(printf("Calling Segment_identify_lower to find antisense plus records5 against 3' diagonals\n"));
      plus_records5 = Segment_identify_lower(&plus_nrecords5,
#ifdef LARGE_GENOMES
					     this5->plus_positions_high,
#endif
					     this5->plus_positions,this5->plus_npositions,this5->validp,
					     this5->forward_oligos,repetitive_ef64,

					     this5->streamptr_alloc,this5->streamsize_alloc,
					     this5->querypos_diagterm_alloc,this5->mergeinfo,
					     /*max_pairlength*/pairmax_linear,overall_max_distance_5,querylength5,
					     gplus3_diagonals,gplus3_ndiagonals,/*plusp*/true);
      
      debug(printf("Calling Segment_identify_higher to find antisense minus records5 against 3' diagonals\n"));
      minus_records5 = Segment_identify_higher(&minus_nrecords5,
#ifdef LARGE_GENOMES
					       this5->minus_positions_high,
#endif
					       this5->minus_positions,this5->minus_npositions,this5->validp,
					       this5->revcomp_oligos,repetitive_ef64,

					       this5->streamptr_alloc,this5->streamsize_alloc,
					       this5->querypos_diagterm_alloc,this5->mergeinfo,
					       /*max_pairlength*/pairmax_linear,overall_max_distance_5,querylength5,
					       gminus3_diagonals,gminus3_ndiagonals,/*plusp*/false);
      FREE(gminus3_diagonals);
      FREE(gplus3_diagonals);
      debug(printf("3' antisense diagonals %d and %d => 5' records %d plus and %d minus\n",
		   gplus3_ndiagonals,gminus3_ndiagonals,plus_nrecords5,minus_nrecords5));

      Segment_search_all(&(*found_score_5),&(*found_transcriptp_5),

			 &(*unextended_sense_seg2paths5_gplus),&(*unextended_sense_seg2paths5_gminus),
			 &(*unextended_antisense_seg2paths5_gplus),&(*unextended_antisense_seg2paths5_gminus),
			 
			 &(*sense_seg2paths5_gplus),&(*sense_seg2paths5_gminus),
			 &(*antisense_seg2paths5_gplus),&(*antisense_seg2paths5_gminus),
			 plus_records5,plus_nrecords5,minus_records5,minus_nrecords5,
			 
			 queryseq5,queryuc_ptr_5,queryrc5,querylength5,mismatch_positions_alloc_5,
			 novel_diagonals_alloc,localdb_alloc,
			 this5,knownsplicing,knownindels,
			 query5_compress_fwd,query5_compress_rev,
			 max_insertionlen_5,max_deletionlen_5,nmismatches_allowed_5,
			 overall_max_distance_5,overall_end_distance_5,
			 genestrand,/*paired_end_p*/true,/*first_read_p*/true,
			 univdiagpool,intlistpool,uintlistpool,univcoordlistpool,listpool,
			 pathpool,transcriptpool,vectorpool,hitlistpool,spliceendsgen5,
			 /*method*/SEGMENT2,pass);
      FREE(plus_records5); FREE(minus_records5);
    }
    *last_method_5 = SEGMENT2;
  }

  if (use_unextended_p == true ||
      (*found_score_3 > sufficient_score_3 || *found_transcriptp_3 == false ||
       (*found_score_5 <= sufficient_score_5 && *found_transcriptp_5 == true))) {
    /* Sense */
    if (use_unextended_p == true) {
      gplus5_diagonals = Path_genomiclows(&gplus5_ndiagonals,this5->unextended_sense_paths_gplus);
      gminus5_diagonals = Path_genomichighs(&gminus5_ndiagonals,this5->unextended_sense_paths_gminus);
    } else {
      gplus5_diagonals = Path_genomiclows(&gplus5_ndiagonals,this5->sense_paths_gplus);
      gminus5_diagonals = Path_genomichighs(&gminus5_ndiagonals,this5->sense_paths_gminus);
    }
    
    if (this3->all_oligos_gen_filledp == false) {
      Stage1_fill_all_oligos_gen(this3,querylength3,genestrand);
    }
    if (this3->all_positions_gen_filledp == false) {
      Stage1_fill_all_positions_gen(this3,querylength3,genestrand);
    }

    debug(printf("Calling Segment_identify_higher to find sense plus records3 against 5' diagonals\n"));
    plus_records3 = Segment_identify_higher(&plus_nrecords3,
#ifdef LARGE_GENOMES
					    this3->plus_positions_high,
#endif
					    this3->plus_positions,this3->plus_npositions,this3->validp,
					    this3->forward_oligos,repetitive_ef64,

					    this3->streamptr_alloc,this3->streamsize_alloc,
					    this3->querypos_diagterm_alloc,this3->mergeinfo,
					    /*max_pairlength*/pairmax_linear,overall_max_distance_3,querylength3,
					    gplus5_diagonals,gplus5_ndiagonals,/*plusp*/true);
    
    debug(printf("Calling Segment_identify_lower to find sense minus records3 against 5' diagonals\n"));
    minus_records3 = Segment_identify_lower(&minus_nrecords3,
#ifdef LARGE_GENOMES
					    this3->minus_positions_high,
#endif
					    this3->minus_positions,this3->minus_npositions,this3->validp,
					    this3->revcomp_oligos,repetitive_ef64,

					    this3->streamptr_alloc,this3->streamsize_alloc,
					    this3->querypos_diagterm_alloc,this3->mergeinfo,
					    /*max_pairlength*/pairmax_linear,overall_max_distance_3,querylength3,
					    gminus5_diagonals,gminus5_ndiagonals,/*plusp*/false);
    FREE(gminus5_diagonals);
    FREE(gplus5_diagonals);
    debug(printf("5' sense diagonals %d and %d => 3' records %d plus and %d minus\n",
		 gplus5_ndiagonals,gminus5_ndiagonals,plus_nrecords3,minus_nrecords3));
    
    Segment_search_all(&(*found_score_3),&(*found_transcriptp_3),

		       &(*unextended_sense_seg2paths3_gplus),&(*unextended_sense_seg2paths3_gminus),
		       &(*unextended_antisense_seg2paths3_gplus),&(*unextended_antisense_seg2paths3_gminus),

		       &(*sense_seg2paths3_gplus),&(*sense_seg2paths3_gminus),
		       &(*antisense_seg2paths3_gplus),&(*antisense_seg2paths3_gminus),
		       plus_records3,plus_nrecords3,minus_records3,minus_nrecords3,
		       
		       queryseq3,queryuc_ptr_3,queryrc3,querylength3,mismatch_positions_alloc_3,
		       novel_diagonals_alloc,localdb_alloc,
		       this3,knownsplicing,knownindels,
		       query3_compress_fwd,query3_compress_rev,
		       max_insertionlen_3,max_deletionlen_3,nmismatches_allowed_3,
		       overall_max_distance_3,overall_end_distance_3,
		       genestrand,/*paired_end_p*/true,/*first_read_p*/false,
		       univdiagpool,intlistpool,uintlistpool,univcoordlistpool,listpool,
		       pathpool,transcriptpool,vectorpool,hitlistpool,spliceendsgen3,
		       /*method*/SEGMENT2,pass);
    FREE(plus_records3); FREE(minus_records3);


    if (splicingp == true) {
      /* Antisense */
      if (use_unextended_p == true) {
	gplus5_diagonals = Path_genomiclows(&gplus5_ndiagonals,this5->unextended_antisense_paths_gplus);
	gminus5_diagonals = Path_genomichighs(&gminus5_ndiagonals,this5->unextended_antisense_paths_gminus);
      } else {
	gplus5_diagonals = Path_genomiclows(&gplus5_ndiagonals,this5->antisense_paths_gplus);
	gminus5_diagonals = Path_genomichighs(&gminus5_ndiagonals,this5->antisense_paths_gminus);
      }
    
      debug(printf("Calling Segment_identify_higher to find antisense plus records3 against 5' diagonals\n"));
      plus_records3 = Segment_identify_higher(&plus_nrecords3,
#ifdef LARGE_GENOMES
					      this3->plus_positions_high,
#endif
					      this3->plus_positions,this3->plus_npositions,this3->validp,
					      this3->forward_oligos,repetitive_ef64,

					      this3->streamptr_alloc,this3->streamsize_alloc,
					      this3->querypos_diagterm_alloc,this3->mergeinfo,
					      /*max_pairlength*/pairmax_linear,overall_max_distance_3,querylength3,
					      gplus5_diagonals,gplus5_ndiagonals,/*plusp*/true);
      
      debug(printf("Calling Segment_identify_lower to find antisense minus records3 against 5' diagonals\n"));
      minus_records3 = Segment_identify_lower(&minus_nrecords3,
#ifdef LARGE_GENOMES
					      this3->minus_positions_high,
#endif
					      this3->minus_positions,this3->minus_npositions,this3->validp,
					      this3->revcomp_oligos,repetitive_ef64,

					      this3->streamptr_alloc,this3->streamsize_alloc,
					      this3->querypos_diagterm_alloc,this3->mergeinfo,
					      /*max_pairlength*/pairmax_linear,overall_max_distance_3,querylength3,
					      gminus5_diagonals,gminus5_ndiagonals,/*plusp*/false);
      FREE(gminus5_diagonals);
      FREE(gplus5_diagonals);
      debug(printf("5' antisense diagonals %d and %d => 3' records %d plus and %d minus\n",
		   gplus5_ndiagonals,gminus5_ndiagonals,plus_nrecords3,minus_nrecords3));
      
      Segment_search_all(&(*found_score_3),&(*found_transcriptp_3),

			 &(*unextended_sense_seg2paths3_gplus),&(*unextended_sense_seg2paths3_gminus),
			 &(*unextended_antisense_seg2paths3_gplus),&(*unextended_antisense_seg2paths3_gminus),

			 &(*sense_seg2paths3_gplus),&(*sense_seg2paths3_gminus),
			 &(*antisense_seg2paths3_gplus),&(*antisense_seg2paths3_gminus),
			 plus_records3,plus_nrecords3,minus_records3,minus_nrecords3,

			 queryseq3,queryuc_ptr_3,queryrc3,querylength3,mismatch_positions_alloc_3,
			 novel_diagonals_alloc,localdb_alloc,
			 this3,knownsplicing,knownindels,
			 query3_compress_fwd,query3_compress_rev,
			 max_insertionlen_3,max_deletionlen_3,nmismatches_allowed_3,
			 overall_max_distance_3,overall_end_distance_3,
			 genestrand,/*paired_end_p*/true,/*first_read_p*/false,
			 univdiagpool,intlistpool,uintlistpool,univcoordlistpool,listpool,
			 pathpool,transcriptpool,vectorpool,hitlistpool,spliceendsgen3,
			 /*method*/SEGMENT2,pass);
      FREE(plus_records3); FREE(minus_records3);
    }

    *last_method_3 = SEGMENT2;
  }
  

  *sense_seg2paths5_gplus = Path_filter(*sense_seg2paths5_gplus,
					intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
  *sense_seg2paths5_gminus = Path_filter(*sense_seg2paths5_gminus,
					 intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
  *sense_seg2paths3_gplus = Path_filter(*sense_seg2paths3_gplus,
					intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
  *sense_seg2paths3_gminus = Path_filter(*sense_seg2paths3_gminus,
					 intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);

  debug(printf("Calling Concordance_simple in paired_read_segment_search, sense\n"));
  pathpairs = Concordance_simple(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,
				 *sense_seg2paths5_gplus,*sense_seg2paths5_gminus,
				 *sense_seg2paths3_gplus,*sense_seg2paths3_gminus,
				 
				 this5->sense_paths_gplus,this5->sense_paths_gminus,
				 this3->sense_paths_gplus,this3->sense_paths_gminus,
				 
				 query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				 queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				 this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 
				 novel_diagonals_alloc,localdb_alloc,
				 knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,

				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 overall_end_distance_5,overall_end_distance_3,
				 
				 intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				 vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  debug(printf("Got %d pathpairs\n",List_length(pathpairs)));

  if (splicingp == true) {
    debug(printf("Calling Concordance_simple in paired_read_segment_search, antisense\n"));
    *antisense_seg2paths5_gplus = Path_filter(*antisense_seg2paths5_gplus,
					      intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    *antisense_seg2paths5_gminus = Path_filter(*antisense_seg2paths5_gminus,
					       intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    *antisense_seg2paths3_gplus = Path_filter(*antisense_seg2paths3_gplus,
					      intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    *antisense_seg2paths3_gminus = Path_filter(*antisense_seg2paths3_gminus,
					      intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);

    pathpairs = Concordance_simple(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,
				   *antisense_seg2paths5_gplus,*antisense_seg2paths5_gminus,
				   *antisense_seg2paths3_gplus,*antisense_seg2paths3_gminus,
				   
				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   
				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				   
				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,

				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				   
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
    debug(printf("Got %d pathpairs\n",List_length(pathpairs)));
  }

  debug(printf("After paired_segment_search on complete paths, we have %d pathpairs\n\n",List_length(pathpairs)));
  return pathpairs;
}



static List_T
paired_read_segment_search (int *found_score_paired, int *found_score_5, int *found_score_3,
			    bool *found_transcriptp_5, bool *found_transcriptp_3,
			    Method_T *last_method_5, Method_T *last_method_3,

			    List_T pathpairs, T this5, T this3, EF64_T repetitive_ef64,

			    Shortread_T queryseq5, Shortread_T queryseq3,
			    char *queryuc_ptr_5, char *queryrc5, int querylength5,
			    char *queryuc_ptr_3, char *queryrc3, int querylength3,
			    Knownsplicing_T knownsplicing, Knownindels_T knownindels,

			    int *mismatch_positions_alloc_5, int *mismatch_positions_alloc_3,
			    Univcoord_T *novel_diagonals_alloc, unsigned short *localdb_alloc,
			    Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
			    Compress_T query3_compress_fwd, Compress_T query3_compress_rev,
			    
			    int nmismatches_allowed_5, int nmismatches_allowed_3,
			    int max_insertionlen_5, int max_insertionlen_3, int max_deletionlen_5, int max_deletionlen_3,
			    int genestrand, Chrpos_T pairmax_linear, Chrpos_T overall_max_distance_5, Chrpos_T overall_max_distance_3,
			    Chrpos_T overall_end_distance_5, Chrpos_T overall_end_distance_3,
			      
			    Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
			    Listpool_T listpool, Univdiagpool_T univdiagpool,
			    Pathpool_T pathpool, Transcriptpool_T transcriptpool,
			    Vectorpool_T vectorpool, Hitlistpool_T hitlistpool,
			    Spliceendsgen_T spliceendsgen5, Spliceendsgen_T spliceendsgen3, Pass_T pass,
			    int sufficient_score_5, int sufficient_score_3, int sufficient_score_paired) {
  
  /* For Segment_search */
  List_T sense_seg2paths5_gplus = NULL, sense_seg2paths5_gminus = NULL,
    sense_seg2paths3_gplus = NULL, sense_seg2paths3_gminus = NULL,
    antisense_seg2paths5_gplus = NULL, antisense_seg2paths5_gminus = NULL,
    antisense_seg2paths3_gplus = NULL, antisense_seg2paths3_gminus = NULL;

  List_T unextended_sense_seg2paths5_gplus = NULL, unextended_sense_seg2paths5_gminus = NULL,
    unextended_sense_seg2paths3_gplus = NULL, unextended_sense_seg2paths3_gminus = NULL,
    unextended_antisense_seg2paths5_gplus = NULL, unextended_antisense_seg2paths5_gminus = NULL,
    unextended_antisense_seg2paths3_gplus = NULL, unextended_antisense_seg2paths3_gminus = NULL;

  pathpairs =
    paired_search(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
		  &(*found_transcriptp_5),&(*found_transcriptp_3),
		  &(*last_method_5),&(*last_method_3),

		  &unextended_sense_seg2paths5_gplus,
		  &unextended_sense_seg2paths5_gminus,
		  &unextended_sense_seg2paths3_gplus,
		  &unextended_sense_seg2paths3_gminus,
		  &unextended_antisense_seg2paths5_gplus,
		  &unextended_antisense_seg2paths5_gminus,
		  &unextended_antisense_seg2paths3_gplus,
		  &unextended_antisense_seg2paths3_gminus,

		  &sense_seg2paths5_gplus,&sense_seg2paths5_gminus,
		  &sense_seg2paths3_gplus,&sense_seg2paths3_gminus,
		  &antisense_seg2paths5_gplus,&antisense_seg2paths5_gminus,
		  &antisense_seg2paths3_gplus,&antisense_seg2paths3_gminus,

		  pathpairs,this5,this3,repetitive_ef64,queryseq5,queryseq3,

		  queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
		  knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
		  novel_diagonals_alloc,localdb_alloc,
		  query5_compress_fwd,query5_compress_rev,
		  query3_compress_fwd,query3_compress_rev,
		  /*nmismatches_allowed_5*/2 * nmismatches_allowed_5,
		  /*nmismatches_allowed_3*/2 * nmismatches_allowed_3,
		  max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
		  genestrand,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
		  overall_end_distance_5,overall_end_distance_3,
		  intlistpool,uintlistpool,univcoordlistpool,listpool,univdiagpool,
		  pathpool,transcriptpool,vectorpool,hitlistpool,
		  spliceendsgen5,spliceendsgen3,pass,
		  sufficient_score_5,sufficient_score_3,/*use_unextended_p*/false);

#if 0
  if (pathpairs == NULL || *found_score_paired > sufficient_score_paired) {
    pathpairs =
      paired_search(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
		    &(*found_transcriptp_5),&(*found_transcriptp_3),
		    &(*last_method_5),&(*last_method_3),
		    
		    &unextended_sense_seg2paths5_gplus,
		    &unextended_sense_seg2paths5_gminus,
		    &unextended_sense_seg2paths3_gplus,
		    &unextended_sense_seg2paths3_gminus,
		    &unextended_antisense_seg2paths5_gplus,
		    &unextended_antisense_seg2paths5_gminus,
		    &unextended_antisense_seg2paths3_gplus,
		    &unextended_antisense_seg2paths3_gminus,

		    &sense_seg2paths5_gplus,&sense_seg2paths5_gminus,
		    &sense_seg2paths3_gplus,&sense_seg2paths3_gminus,
		    &antisense_seg2paths5_gplus,&antisense_seg2paths5_gminus,
		    &antisense_seg2paths3_gplus,&antisense_seg2paths3_gminus,

		    pathpairs,this5,this3,repetitive_ef64,queryseq5,queryseq3,

		    queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
		    knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
		    novel_diagonals_alloc,localdb_alloc,
		    query5_compress_fwd,query5_compress_rev,
		    query3_compress_fwd,query3_compress_rev,
		    /*nmismatches_allowed_5*/2 * nmismatches_allowed_5,
		    /*nmismatches_allowed_3*/2 * nmismatches_allowed_3,
		    max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
		    genestrand,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
		    overall_end_distance_5,overall_end_distance_3,
		    intlistpool,uintlistpool,univcoordlistpool,listpool,univdiagpool,
		    pathpool,transcriptpool,vectorpool,hitlistpool,
		    spliceendsgen5,spliceendsgen3,pass,
		    sufficient_score_5,sufficient_score_3,/*use_unextended_p*/true);
  }
#endif

  if (pathpairs != NULL && *found_score_paired <= sufficient_score_paired) {
    debug0(print_pathpairs_contents(pathpairs));

    /* Should not need complete paths any more */
    Path_gc(&sense_seg2paths5_gplus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&sense_seg2paths5_gminus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&sense_seg2paths3_gplus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&sense_seg2paths3_gminus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&antisense_seg2paths5_gplus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&antisense_seg2paths5_gminus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&antisense_seg2paths3_gplus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    Path_gc(&antisense_seg2paths3_gminus,
	    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);

    /* Append unextended paths to old ones for fusions */
    this5->unextended_sense_paths_gplus = List_append(this5->unextended_sense_paths_gplus,unextended_sense_seg2paths5_gplus);
    this5->unextended_sense_paths_gminus = List_append(this5->unextended_sense_paths_gminus,unextended_sense_seg2paths5_gminus);
    this5->unextended_antisense_paths_gplus = List_append(this5->unextended_antisense_paths_gplus,unextended_antisense_seg2paths5_gplus);
    this5->unextended_antisense_paths_gminus = List_append(this5->unextended_antisense_paths_gminus,unextended_antisense_seg2paths5_gminus);

    this3->unextended_sense_paths_gplus = List_append(this3->unextended_sense_paths_gplus,unextended_sense_seg2paths3_gplus);
    this3->unextended_sense_paths_gminus = List_append(this3->unextended_sense_paths_gminus,unextended_sense_seg2paths3_gminus);
    this3->unextended_antisense_paths_gplus = List_append(this3->unextended_antisense_paths_gplus,unextended_antisense_seg2paths3_gplus);
    this3->unextended_antisense_paths_gminus = List_append(this3->unextended_antisense_paths_gminus,unextended_antisense_seg2paths3_gminus);

    return pathpairs;

  } else {
    /* Append complete paths to old ones for Concordance_simple */
    this5->sense_paths_gplus = List_append(this5->sense_paths_gplus,sense_seg2paths5_gplus);
    this5->sense_paths_gminus = List_append(this5->sense_paths_gminus,sense_seg2paths5_gminus);
    this5->antisense_paths_gplus = List_append(this5->antisense_paths_gplus,antisense_seg2paths5_gplus);
    this5->antisense_paths_gminus = List_append(this5->antisense_paths_gminus,antisense_seg2paths5_gminus);

    this3->sense_paths_gplus = List_append(this3->sense_paths_gplus,sense_seg2paths3_gplus);
    this3->sense_paths_gminus = List_append(this3->sense_paths_gminus,sense_seg2paths3_gminus);
    this3->antisense_paths_gplus = List_append(this3->antisense_paths_gplus,antisense_seg2paths3_gplus);
    this3->antisense_paths_gminus = List_append(this3->antisense_paths_gminus,antisense_seg2paths3_gminus);
  }

  if (List_length(unextended_sense_seg2paths5_gplus) > MAX_UNEXTENDED_HITS) {
    debug(printf("Excessive hits in 5' unextended sense gplus: Reducing from %d",List_length(unextended_sense_seg2paths5_gplus)));
    unextended_sense_seg2paths5_gplus = Path_filter(unextended_sense_seg2paths5_gplus,
						      intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(unextended_sense_seg2paths5_gplus)));
  }
  if (List_length(unextended_sense_seg2paths5_gminus) > MAX_UNEXTENDED_HITS) {
    debug(printf("Excessive hits in 5' sense gminus: Reducing from %d",List_length(unextended_sense_seg2paths5_gminus)));
    unextended_sense_seg2paths5_gminus = Path_filter(unextended_sense_seg2paths5_gminus,
						       intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(unextended_sense_seg2paths5_gminus)));
  }
  if (List_length(unextended_sense_seg2paths3_gplus) > MAX_UNEXTENDED_HITS) {
    debug(printf("Excessive hits in 3' sense gplus: Reducing from %d",List_length(unextended_sense_seg2paths3_gplus)));
    unextended_sense_seg2paths3_gplus = Path_filter(unextended_sense_seg2paths3_gplus,
						      intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(unextended_sense_seg2paths3_gplus)));
  }
  if (List_length(unextended_sense_seg2paths3_gminus) > MAX_UNEXTENDED_HITS) {
    debug(printf("Excessive hits in 3' sense gminus: Reducing from %d",List_length(unextended_sense_seg2paths3_gminus)));
    unextended_sense_seg2paths3_gminus = Path_filter(unextended_sense_seg2paths3_gminus,
						       intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(unextended_sense_seg2paths3_gminus)));
  }

  debug(printf("Calling Concordance_simple with unextended seg2 paths, sense\n"));
  pathpairs = Concordance_simple(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				 /*newpaths5_gplus*/unextended_sense_seg2paths5_gplus,
				 /*newpaths5_gminus*/unextended_sense_seg2paths5_gminus,
				 /*newpaths3_gplus*/unextended_sense_seg2paths3_gplus,
				 /*newpaths3_gminus*/unextended_sense_seg2paths3_gminus,
				 
				 this5->sense_paths_gplus,this5->sense_paths_gminus,
				 this3->sense_paths_gplus,this3->sense_paths_gminus,
				 
				 query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				 queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				 this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 
				 novel_diagonals_alloc,localdb_alloc,
				 knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 overall_end_distance_5,overall_end_distance_3,
				 
				 intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				 vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  debug(printf("Got %d pathpairs\n",List_length(pathpairs)));
  
  if (splicingp == true) {
    if (List_length(unextended_antisense_seg2paths5_gplus) > MAX_UNEXTENDED_HITS) {
      debug(printf("Excessive hits in 5' unextended antisense gplus: Reducing from %d",List_length(unextended_antisense_seg2paths5_gplus)));
      unextended_antisense_seg2paths5_gplus = Path_filter(unextended_antisense_seg2paths5_gplus,
							    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(unextended_antisense_seg2paths5_gplus)));
    }
    if (List_length(unextended_antisense_seg2paths5_gminus) > MAX_UNEXTENDED_HITS) {
      debug(printf("Excessive hits in 5' antisense gminus: Reducing from %d",List_length(unextended_antisense_seg2paths5_gminus)));
      unextended_antisense_seg2paths5_gminus = Path_filter(unextended_antisense_seg2paths5_gminus,
							     intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(unextended_antisense_seg2paths5_gminus)));
    }
    if (List_length(unextended_antisense_seg2paths3_gplus) > MAX_UNEXTENDED_HITS) {
      debug(printf("Excessive hits in 3' antisense gplus: Reducing from %d",List_length(unextended_antisense_seg2paths3_gplus)));
      unextended_antisense_seg2paths3_gplus = Path_filter(unextended_antisense_seg2paths3_gplus,
							    intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(unextended_antisense_seg2paths3_gplus)));
    }
    if (List_length(unextended_antisense_seg2paths3_gminus) > MAX_UNEXTENDED_HITS) {
      debug(printf("Excessive hits in 3' antisense gminus: Reducing from %d",List_length(unextended_antisense_seg2paths3_gminus)));
      unextended_antisense_seg2paths3_gminus = Path_filter(unextended_antisense_seg2paths3_gminus,
							     intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(unextended_antisense_seg2paths3_gminus)));
    }
    debug(printf("Calling Concordance_simple with unextended seg2 paths, antisense\n"));
    pathpairs = Concordance_simple(&(*found_score_paired),&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,
				   /*newpaths5_gplus*/unextended_antisense_seg2paths5_gplus,
				   /*newpaths5_gminus*/unextended_antisense_seg2paths5_gminus,
				   /*newpaths3_gplus*/unextended_antisense_seg2paths3_gplus,
				   /*newpaths3_gminus*/unextended_antisense_seg2paths3_gminus,
				   
				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   
				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				   
				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				   
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
    debug(printf("Got %d pathpairs\n",List_length(pathpairs)));
  }

  debug(printf("After looking at unextended seg2 paths, we have %d pathpairs and found scores %d and %d\n",
	       List_length(pathpairs),*found_score_5,*found_score_3));

  /* Append unextended paths to old ones for fusions */
  this5->unextended_sense_paths_gplus = List_append(this5->unextended_sense_paths_gplus,unextended_sense_seg2paths5_gplus);
  this5->unextended_sense_paths_gminus = List_append(this5->unextended_sense_paths_gminus,unextended_sense_seg2paths5_gminus);
  this5->unextended_antisense_paths_gplus = List_append(this5->unextended_antisense_paths_gplus,unextended_antisense_seg2paths5_gplus);
  this5->unextended_antisense_paths_gminus = List_append(this5->unextended_antisense_paths_gminus,unextended_antisense_seg2paths5_gminus);

  this3->unextended_sense_paths_gplus = List_append(this3->unextended_sense_paths_gplus,unextended_sense_seg2paths3_gplus);
  this3->unextended_sense_paths_gminus = List_append(this3->unextended_sense_paths_gminus,unextended_sense_seg2paths3_gminus);
  this3->unextended_antisense_paths_gplus = List_append(this3->unextended_antisense_paths_gplus,unextended_antisense_seg2paths3_gplus);
  this3->unextended_antisense_paths_gminus = List_append(this3->unextended_antisense_paths_gminus,unextended_antisense_seg2paths3_gminus);

  return pathpairs;
}


static List_T
find_inner_fusions_path5 (int *found_score_5, List_T pathpairs, Path_T path5, List_T singlepaths3,
			  Stage1_T this5, Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
			  Shortread_T queryseq5, Shortread_T queryseq3, char *queryuc_ptr_5, char *queryrc5,
			  Univcoord_T *novel_diagonals_alloc, unsigned short *localdb_alloc,
			  Knownsplicing_T knownsplicing,
			  int nmismatches_allowed_5, int max_insertionlen_5, int max_deletionlen_5,
			  Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
			  Listpool_T listpool, Pathpool_T pathpool, Vectorpool_T vectorpool,
			  Hitlistpool_T hitlistpool, Transcriptpool_T transcriptpool) {
  List_T p;
  Path_T newpath, path3;
  Pathpair_T pathpair;

  for (p = singlepaths3; p != NULL; p = List_next(p)) {
    path3 = (Path_T) List_head(p); /* anchor */
    /* path3 determines overall plusp, and query_compress and queryptr for main part of path5 */
    if (Path_unextended_querystart_p(path5,/*endtrim_allowed*/8,/*allow_ambig_p*/true) == true) {
      /* Skip.  Want fusion alignments to extend to the end */
    } else if (path3->plusp == true) {
      /* Case 1: fusion5 plus, main5 plus; anchor3 plus */
      /* Case 2: fusion5 minus, main5 plus; anchor3 plus */
      if ((newpath = Path_fusion_inner_qend(&(*found_score_5),/*fusion5*/path5,/*anchor3*/path3,
					    /*queryptr_main*/queryuc_ptr_5,/*main_plusp*/true,path5->querylength,
					    /*main_chrnum*/path3->chrnum,path3->chroffset,path3->chrhigh,
					    novel_diagonals_alloc,localdb_alloc,
					    this5->streamspace_max_alloc,this5->streamspace_alloc,
					    this5->streamptr_alloc,this5->streamsize_alloc,this5->mergeinfo,
					    this5->indelinfo,this5->spliceinfo,knownsplicing,
					    /*query_compress_main*/query5_compress_fwd,query5_compress_fwd,query5_compress_rev,
					    queryseq5,path5->genestrand,nmismatches_allowed_5,
					    max_insertionlen_5,max_deletionlen_5,
					    intlistpool,uintlistpool,univcoordlistpool,
					    listpool,pathpool,vectorpool,
					    transcriptpool)) != NULL &&
	  (pathpair = Pathpair_new_inner_fusion(/*pathL*/newpath,/*pathH*/path3,
						/*queryseqL*/queryseq5,/*queryseqH*/queryseq3,/*plusp*/true,
						intlistpool,univcoordlistpool,listpool,pathpool,
						vectorpool,transcriptpool,/*copyLp*/false,/*copyHp*/true)) != NULL) {
	pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				 hitlistpool_trace(__FILE__,__LINE__));
      }
    } else {
      /* Case 4': anchor3 minus; main5 minus, fusion5 plus */
      /* Case 3': anchor3 minus; main5 minus, fusion5 minus */
      if ((newpath = Path_fusion_inner_qend(&(*found_score_5),/*fusion5*/path5,/*anchor3*/path3,
					    /*queryptr_main*/queryrc5,/*main_plusp*/false,path5->querylength,
					    /*main_chrnum*/path3->chrnum,path3->chroffset,path3->chrhigh,
					    novel_diagonals_alloc,localdb_alloc,
					    this5->streamspace_max_alloc,this5->streamspace_alloc,
					    this5->streamptr_alloc,this5->streamsize_alloc,this5->mergeinfo,
					    this5->indelinfo,this5->spliceinfo,knownsplicing,
					    /*query_compress_main*/query5_compress_rev,query5_compress_fwd,query5_compress_rev,
					    queryseq5,path5->genestrand,nmismatches_allowed_5,
					    max_insertionlen_5,max_deletionlen_5,
					    intlistpool,uintlistpool,univcoordlistpool,
					    listpool,pathpool,vectorpool,
					    transcriptpool)) != NULL &&
	  (pathpair = Pathpair_new_inner_fusion(/*pathL*/path3,/*pathH*/newpath,
						/*queryseqL*/queryseq3,/*queryseqH*/queryseq5,/*plusp*/false,
						intlistpool,univcoordlistpool,listpool,pathpool,
						vectorpool,transcriptpool,/*copyLp*/true,/*copyHp*/false)) != NULL) {
	pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				 hitlistpool_trace(__FILE__,__LINE__));
      }
    }
  }

  return pathpairs;
}


static List_T
find_inner_fusions_path3 (int *found_score_3, List_T pathpairs, Path_T path3, List_T singlepaths5,
			  Stage1_T this3, Compress_T query3_compress_fwd, Compress_T query3_compress_rev,
			  Shortread_T queryseq5, Shortread_T queryseq3, char *queryuc_ptr_3, char *queryrc3,
			  Univcoord_T *novel_diagonals_alloc, unsigned short *localdb_alloc,
			  Knownsplicing_T knownsplicing,
			  int nmismatches_allowed_3, int max_insertionlen_3, int max_deletionlen_3,
			  Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
			  Listpool_T listpool, Pathpool_T pathpool, Vectorpool_T vectorpool,
			  Hitlistpool_T hitlistpool, Transcriptpool_T transcriptpool) {
  List_T p;
  Path_T newpath, path5;
  Pathpair_T pathpair;

  for (p = singlepaths5; p != NULL; p = List_next(p)) {
    path5 = (Path_T) List_head(p);
    /* path5 determines query_compress and queryptr for main part of path3 */
    if (Path_unextended_queryend_p(path3,/*endtrim_allowed*/8,/*allow_ambig_p*/true) == true) {
      /* Skip.  Want fusion alignments to extend to the end */
    } else if (path5->plusp == true) {
      /* Case 3: anchor5 plus; main3 plus, fusion3 plus */
      /* Case 4: anchor5 plus; main3 plus, fusion3 minus */
      if ((newpath = Path_fusion_inner_qstart(&(*found_score_3),/*fusion3*/path3,/*anchor5*/path5,
					      /*queryptr_main*/queryuc_ptr_3,/*main_plusp*/true,path3->querylength,
					      /*main_chrnum*/path5->chrnum,path5->chroffset,path5->chrhigh,
					      novel_diagonals_alloc,localdb_alloc,
					      this3->streamspace_max_alloc,this3->streamspace_alloc,
					      this3->streamptr_alloc,this3->streamsize_alloc,this3->mergeinfo,
					      this3->indelinfo,this3->spliceinfo,knownsplicing,
					      /*query_compress_main*/query3_compress_fwd,query3_compress_fwd,query3_compress_rev,
					      queryseq3,path3->genestrand,nmismatches_allowed_3,
					      max_insertionlen_3,max_deletionlen_3,
					      intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,vectorpool,
					      transcriptpool)) != NULL &&
	  (pathpair = Pathpair_new_inner_fusion(/*pathL*/path5,/*pathH*/newpath,
						/*queryseqL*/queryseq5,/*queryseqH*/queryseq3,/*plusp*/true,
						intlistpool,univcoordlistpool,listpool,pathpool,
						vectorpool,transcriptpool,/*copyLp*/true,/*copyHp*/false)) != NULL) {
	pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				 hitlistpool_trace(__FILE__,__LINE__));
      }

    } else {
      /* Case 2': fusion3 plus, main3 minus; anchor5 minus */
      /* Case 1': fusion3 minus, main3 minus; anchor5 minus */
      if ((newpath = Path_fusion_inner_qstart(&(*found_score_3),/*fusion3*/path3,/*anchor5*/path5,
					      /*queryptr_main*/queryrc3,/*main_plusp*/false,path3->querylength,
					      /*main_chrnum*/path5->chrnum,path5->chroffset,path5->chrhigh,
					      novel_diagonals_alloc,localdb_alloc,
					      this3->streamspace_max_alloc,this3->streamspace_alloc,
					      this3->streamptr_alloc,this3->streamsize_alloc,this3->mergeinfo,
					      this3->indelinfo,this3->spliceinfo,knownsplicing,
					      /*query_compress_main*/query3_compress_rev,query3_compress_fwd,query3_compress_rev,
					      queryseq3,path3->genestrand,nmismatches_allowed_3,
					      max_insertionlen_3,max_deletionlen_3,
					      intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,vectorpool,
					      transcriptpool)) != NULL &&
	  (pathpair = Pathpair_new_inner_fusion(/*pathL*/newpath,/*pathH*/path5,
						/*queryseqL*/queryseq3,/*queryseqH*/queryseq5,/*plusp*/false,
						intlistpool,univcoordlistpool,listpool,pathpool,
						vectorpool,transcriptpool,/*copyLp*/false,/*copyHp*/true)) != NULL) {
	pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				 hitlistpool_trace(__FILE__,__LINE__));
      }
    }
  }

  return pathpairs;
}


#ifdef DEBUG0
static void
print_pathpairs_contents (List_T pathpairs) {
  List_T p;
  Pathpair_T pathpair;

  for (p = pathpairs; p != NULL; p = List_next(p)) {
    pathpair = (Pathpair_T) List_head(p);
    printf("%p %p pathpair\n",pathpair->path5,pathpair->path3);
  }

  return;
}
#endif


static List_T
paired_read (int *found_score_5, int *found_score_3,
	     bool *found_transcriptp_5, bool *found_transcriptp_3,
	     Method_T *last_method_5, Method_T *last_method_3,

	     Shortread_T queryseq5, Shortread_T queryseq3,
	     char *queryuc_ptr_5, char *queryrc5, int querylength5, char *queryuc_ptr_3, char *queryrc3, int querylength3,
	     Knownsplicing_T knownsplicing, Knownindels_T knownindels,

	     int *mismatch_positions_alloc_5, int *mismatch_positions_alloc_3, Univcoord_T *novel_diagonals_alloc,
	     unsigned short *localdb_alloc, T this5, T this3, EF64_T repetitive_ef64,

	     Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
	     Compress_T query3_compress_fwd, Compress_T query3_compress_rev,
	     int nmismatches_allowed_5, int nmismatches_allowed_3,
	     int max_insertionlen_5, int max_insertionlen_3, int max_deletionlen_5, int max_deletionlen_3,
	     int genestrand, Chrpos_T pairmax_linear, Chrpos_T overall_max_distance_5, Chrpos_T overall_max_distance_3,
	     Chrpos_T overall_end_distance_5, Chrpos_T overall_end_distance_3,

	     Trdiagpool_T trdiagpool, Univdiagpool_T univdiagpool,
	     Intlistpool_T intlistpool, Uintlistpool_T uintlistpool,
	     Univcoordlistpool_T univcoordlistpool, Listpool_T listpool, 
	     Trpathpool_T trpathpool, Pathpool_T pathpool, Transcriptpool_T transcriptpool,
	     Vectorpool_T vectorpool, Hitlistpool_T hitlistpool, 
	     Spliceendsgen_T spliceendsgen5, Spliceendsgen_T spliceendsgen3,
	     Pass_T pass, int sufficient_score_5, int sufficient_score_3) {

  List_T pathpairs = NULL;
  int found_score_paired = querylength5 + querylength3;
  int sufficient_score_paired = sufficient_score_5 + sufficient_score_3;

#if 0
  /* Take the larger of maxpaths_search and 10*maxpaths_report */
  maxpairedpaths = maxpaths_search;
  if (maxpairedpaths < 10*maxpaths_report) {
    maxpairedpaths = 10*maxpaths_report;
  }
#endif

  /* TODO: Return level from single_read.  Then if we don't have concordant pathpairs, take the min(level5,level3) and start paired_readfrom t
here */

  /* 1. Greedy method */
  if (transcriptome_align_p == true) {
    debug(printf("Calling single_read_search on 5' read\n"));
    single_read_search_tr(&(*found_score_5),&(*found_transcriptp_5),
			  &(*last_method_5),this5,repetitive_ef64,genestrand,
			  queryseq5,queryuc_ptr_5,queryrc5,querylength5,
			  knownsplicing,knownindels,mismatch_positions_alloc_5,
			  novel_diagonals_alloc,localdb_alloc,
			  query5_compress_fwd,query5_compress_rev,
			  nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
			  overall_max_distance_5,overall_end_distance_5,
			  trdiagpool,univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			  listpool,trpathpool,pathpool,transcriptpool,vectorpool,
			  hitlistpool,spliceendsgen5,
			  /*paired_end_p*/true,/*first_read_p*/true,pass,
			  sufficient_score_5);

    debug(printf("Calling single_read_search on 3' read\n"));
    single_read_search_tr(&(*found_score_3),&(*found_transcriptp_3),
			  &(*last_method_3),this3,repetitive_ef64,genestrand,
			  queryseq3,queryuc_ptr_3,queryrc3,querylength3,
			  knownsplicing,knownindels,mismatch_positions_alloc_3,
			  novel_diagonals_alloc,localdb_alloc,
			  query3_compress_fwd,query3_compress_rev,
			  nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
			  overall_max_distance_3,overall_end_distance_3,
			  trdiagpool,univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			  listpool,trpathpool,pathpool,transcriptpool,vectorpool,
			  hitlistpool,spliceendsgen3,
			  /*paired_end_p*/true,/*first_read_p*/false,pass,
			  sufficient_score_3);

  } else if (splicingp == true) {
    debug(printf("Calling single_read_search on 5' read\n"));
    single_read_search_rna(&(*found_score_5),&(*found_transcriptp_5),
			   &(*last_method_5),this5,repetitive_ef64,genestrand,
			   queryseq5,queryuc_ptr_5,queryrc5,querylength5,
			   knownsplicing,knownindels,mismatch_positions_alloc_5,
			   novel_diagonals_alloc,localdb_alloc,
			   query5_compress_fwd,query5_compress_rev,
			   nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
			   overall_max_distance_5,overall_end_distance_5,
			   univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			   listpool,pathpool,transcriptpool,vectorpool,
			   hitlistpool,spliceendsgen5,
			   /*paired_end_p*/true,/*first_read_p*/true,pass,
			   sufficient_score_5);

    debug(printf("Calling single_read_search on 3' read\n"));
    single_read_search_rna(&(*found_score_3),&(*found_transcriptp_3),
			   &(*last_method_3),this3,repetitive_ef64,genestrand,
			   queryseq3,queryuc_ptr_3,queryrc3,querylength3,
			   knownsplicing,knownindels,mismatch_positions_alloc_3,
			   novel_diagonals_alloc,localdb_alloc,
			   query3_compress_fwd,query3_compress_rev,
			   nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
			   overall_max_distance_3,overall_end_distance_3,
			   univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			   listpool,pathpool,transcriptpool,vectorpool,
			   hitlistpool,spliceendsgen3,
			   /*paired_end_p*/true,/*first_read_p*/false,pass,
			   sufficient_score_3);

  } else {
    debug(printf("Calling single_read_search on 5' read\n"));
    single_read_search_dna(&(*found_score_5),&(*found_transcriptp_5),
			   &(*last_method_5),this5,repetitive_ef64,genestrand,
			   queryseq5,queryuc_ptr_5,queryrc5,querylength5,
			   knownsplicing,knownindels,mismatch_positions_alloc_5,
			   novel_diagonals_alloc,localdb_alloc,
			   query5_compress_fwd,query5_compress_rev,
			   nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
			   overall_max_distance_5,overall_end_distance_5,
			   univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			   listpool,pathpool,transcriptpool,vectorpool,
			   hitlistpool,spliceendsgen5,
			   /*paired_end_p*/true,/*first_read_p*/true,pass,
			   sufficient_score_5);

    debug(printf("Calling single_read_search on 3' read\n"));
    single_read_search_dna(&(*found_score_3),&(*found_transcriptp_3),
			   &(*last_method_3),this3,repetitive_ef64,genestrand,
			   queryseq3,queryuc_ptr_3,queryrc3,querylength3,
			   knownsplicing,knownindels,mismatch_positions_alloc_3,
			   novel_diagonals_alloc,localdb_alloc,
			   query3_compress_fwd,query3_compress_rev,
			   nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
			   overall_max_distance_3,overall_end_distance_3,
			   univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
			   listpool,pathpool,transcriptpool,vectorpool,
			   hitlistpool,spliceendsgen3,
			   /*paired_end_p*/true,/*first_read_p*/false,pass,
			   sufficient_score_3);
  }

  if (this5 == NULL || this3 == NULL) {
    return (List_T) NULL;
  }

  /* If we have too many hits on either end, we need to filter paths
     to avoid combinatorial explosion in Concordance_simple */
  if (List_length(this5->sense_paths_gplus) > MAX_SINGLE_END_HITS) {
    debug(printf("Excessive hits in 5' sense gplus: Reducing from %d",List_length(this5->sense_paths_gplus)));
    this5->sense_paths_gplus = Path_filter(this5->sense_paths_gplus,
					   intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(this5->sense_paths_gplus)));
  }
  if (List_length(this5->sense_paths_gminus) > MAX_SINGLE_END_HITS) {
    debug(printf("Excessive hits in 5' sense gminus: Reducing from %d",List_length(this5->sense_paths_gminus)));
    this5->sense_paths_gminus = Path_filter(this5->sense_paths_gminus,
					   intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(this5->sense_paths_gminus)));
  }
  if (List_length(this3->sense_paths_gplus) > MAX_SINGLE_END_HITS) {
    debug(printf("Excessive hits in 3' sense gplus: Reducing from %d",List_length(this3->sense_paths_gplus)));
    this3->sense_paths_gplus = Path_filter(this3->sense_paths_gplus,
					   intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(this3->sense_paths_gplus)));
  }
  if (List_length(this3->sense_paths_gminus) > MAX_SINGLE_END_HITS) {
    debug(printf("Excessive hits in 3' sense gminus: Reducing from %d",List_length(this3->sense_paths_gminus)));
    this3->sense_paths_gminus = Path_filter(this3->sense_paths_gminus,
					   intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug(printf(" to %d\n",List_length(this3->sense_paths_gminus)));
  }

  debug(printf("Calling Concordance_simple after single_read_search, sense\n"));
  /* Previously had require_transcript_intersectp being (transcriptome != NULL) ? true : false */
  pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,
				 this5->sense_paths_gplus,this5->sense_paths_gminus,
				 this3->sense_paths_gplus,this3->sense_paths_gminus,
				 /*sense_paths5_gplus*/NULL,/*sense_paths5_gminus*/NULL,
				 /*sense_paths3_gplus*/NULL,/*sense_paths3_gminus*/NULL,

				 query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				 queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				 this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,

				 novel_diagonals_alloc,localdb_alloc,
				 knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 overall_end_distance_5,overall_end_distance_3,
				 
				 intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				 vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);

  if (splicingp == true) {
    if (List_length(this5->antisense_paths_gplus) > MAX_SINGLE_END_HITS) {
      debug(printf("Excessive hits in 5' antisense gplus: Reducing from %d",List_length(this5->antisense_paths_gplus)));
      this5->antisense_paths_gplus = Path_filter(this5->antisense_paths_gplus,
						 intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(this5->antisense_paths_gplus)));
    }
    if (List_length(this5->antisense_paths_gminus) > MAX_SINGLE_END_HITS) {
      debug(printf("Excessive hits in 5' antisense gminus: Reducing from %d",List_length(this5->antisense_paths_gminus)));
      this5->antisense_paths_gminus = Path_filter(this5->antisense_paths_gminus,
						  intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(this5->antisense_paths_gminus)));
    }
    if (List_length(this3->antisense_paths_gplus) > MAX_SINGLE_END_HITS) {
      debug(printf("Excessive hits in 3' antisense gplus: Reducing from %d",List_length(this3->antisense_paths_gplus)));
      this3->antisense_paths_gplus = Path_filter(this3->antisense_paths_gplus,
						 intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(this3->antisense_paths_gplus)));
    }
    if (List_length(this3->antisense_paths_gminus) > MAX_SINGLE_END_HITS) {
      debug(printf("Excessive hits in 3' antisense gminus: Reducing from %d",List_length(this3->antisense_paths_gminus)));
      this3->antisense_paths_gminus = Path_filter(this3->antisense_paths_gminus,
						  intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
      debug(printf(" to %d\n",List_length(this3->antisense_paths_gminus)));
    }

    debug(printf("Calling Concordance_simple after single_read_search, antisense\n"));
    /* Previously had require_transcript_intersectp being (transcriptome != NULL) ? true : false */
    pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   /*antisense_paths5_gplus*/NULL,/*antisense_paths5_gminus*/NULL,
				   /*antisense_paths3_gplus*/NULL,/*antisense_paths3_gminus*/NULL,

				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,

				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				 
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  }
  
  debug(printf("After single_read_search, have %d pathpairs and found_scores %d and %d\n",
	       List_length(pathpairs),*found_score_5,*found_score_3));

  if (pathpairs != NULL && found_score_paired <= sufficient_score_paired) {
    debug0(print_pathpairs_contents(pathpairs));
    return pathpairs;
  }


  /* 2. Use transcriptome */
  /* TODO: Find concordance between trpaths and subopt trpaths */
  if (transcriptome != NULL) {
    single_read_transcriptome_search(&(*found_score_5),&(*found_transcriptp_5),
				     &(*last_method_5),this5,knownsplicing,queryseq5,
				     querylength5,mismatch_positions_alloc_5,
				     query5_compress_fwd,query5_compress_rev,
				     max_insertionlen_5,max_deletionlen_5,nmismatches_allowed_5,
				     trdiagpool,intlistpool,uintlistpool,univcoordlistpool,
				     listpool,trpathpool,pathpool,transcriptpool,
				     hitlistpool,/*first_read_p*/true);

    single_read_transcriptome_search(&(*found_score_3),&(*found_transcriptp_3),
				     &(*last_method_3),this3,knownsplicing,queryseq3,
				     querylength3,mismatch_positions_alloc_3,
				     query3_compress_fwd,query3_compress_rev,
				     max_insertionlen_3,max_deletionlen_3,nmismatches_allowed_3,
				     trdiagpool,intlistpool,uintlistpool,univcoordlistpool,
				     listpool,trpathpool,pathpool,transcriptpool,
				     hitlistpool,/*first_read_p*/false);

    debug(printf("Calling Concordance_simple after single_read_transcriptome_search, sense\n"));
    pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				   this5->sense_paths_gplus,this5->sense_paths_gminus,
				   this3->sense_paths_gplus,this3->sense_paths_gminus,
				   /*sense_paths5_gplus*/NULL,/*sense_paths5_gminus*/NULL,
				   /*sense_paths3_gplus*/NULL,/*sense_paths3_gminus*/NULL,
				   
				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				   
				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				   
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/true,pass);
    
    debug(printf("Calling Concordance_simple after single_read_transcriptome_search, antisense\n"));
    pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,
				   
				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   /*antisense_paths5_gplus*/NULL,/*antisense_paths5_gminus*/NULL,
				   /*antisense_paths3_gplus*/NULL,/*antisense_paths3_gminus*/NULL,

				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,

				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				 
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/true,pass);

    debug(printf("After single_read_transcriptome_search, have %d pathpairs and found_scores %d and %d\n",
		 List_length(pathpairs),*found_score_5,*found_score_3));

    if (pathpairs != NULL && found_score_paired <= sufficient_score_paired) {
      debug0(print_pathpairs_contents(pathpairs));
      return pathpairs;
    }
  }


  /* 3.  Try extending or combining paths, and find concordance on extended paths */
  single_read_extend(&(*found_score_5),&(*found_transcriptp_5),this5,
		     queryseq5,queryuc_ptr_5,queryrc5,querylength5,
		     knownsplicing,knownindels,mismatch_positions_alloc_5,
		     novel_diagonals_alloc,localdb_alloc,
		     query5_compress_fwd,query5_compress_rev,
		     nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
		     overall_end_distance_5,
		     intlistpool,uintlistpool,univcoordlistpool,
		     listpool,pathpool,transcriptpool,vectorpool,
		     hitlistpool,spliceendsgen5,pass);

  single_read_extend(&(*found_score_3),&(*found_transcriptp_3),this3,
		     queryseq3,queryuc_ptr_3,queryrc3,querylength3,
		     knownsplicing,knownindels,mismatch_positions_alloc_3,
		     novel_diagonals_alloc,localdb_alloc,
		     query3_compress_fwd,query3_compress_rev,
		     nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
		     overall_end_distance_3,
		     intlistpool,uintlistpool,univcoordlistpool,
		     listpool,pathpool,transcriptpool,vectorpool,
		     hitlistpool,spliceendsgen3,pass);

  debug(printf("Calling Concordance_simple with extended paths, sense\n"));
  pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				 /*newpaths5_gplus*/this5->extended_sense_paths_gplus,
				 /*newpaths5_gminus*/this5->extended_sense_paths_gminus,
				 /*newpaths3_gplus*/this3->extended_sense_paths_gplus,
				 /*newpaths3_gminus*/this3->extended_sense_paths_gminus,
				 
				 this5->sense_paths_gplus,this5->sense_paths_gminus,
				 this3->sense_paths_gplus,this3->sense_paths_gminus,
				 
				 query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				 queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				 this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 
				 novel_diagonals_alloc,localdb_alloc,
				 knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 overall_end_distance_5,overall_end_distance_3,
				 
				 intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				 vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);

  if (splicingp == true) {
    pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				   /*newpaths5_gplus*/this5->extended_antisense_paths_gplus,
				   /*newpaths5_gminus*/this5->extended_antisense_paths_gminus,
				   /*newpaths3_gplus*/this3->extended_antisense_paths_gplus,
				   /*newpaths3_gminus*/this3->extended_antisense_paths_gminus,
				   
				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   
				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				   
				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				   
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  }

  debug(printf("After looking at extended paths, we have %d pathpairs and found scores %d and %d\n",
	       List_length(pathpairs),*found_score_5,*found_score_3));

  if (pathpairs != NULL && found_score_paired <= sufficient_score_paired) {
    debug0(print_pathpairs_contents(pathpairs));
    return pathpairs;
  }


  /* 4. Find concordance on unextended paths */
  /* First, accumulate extended paths into old paths */
  this5->sense_paths_gplus = List_append(this5->sense_paths_gplus,this5->extended_sense_paths_gplus);
  this5->sense_paths_gminus = List_append(this5->sense_paths_gminus,this5->extended_sense_paths_gminus);
  this5->antisense_paths_gplus = List_append(this5->antisense_paths_gplus,this5->extended_antisense_paths_gplus);
  this5->antisense_paths_gminus = List_append(this5->antisense_paths_gminus,this5->extended_antisense_paths_gminus);
  this5->extended_sense_paths_gplus = (List_T) NULL;
  this5->extended_sense_paths_gminus = (List_T) NULL;
  this5->extended_antisense_paths_gplus = (List_T) NULL;
  this5->extended_antisense_paths_gminus = (List_T) NULL;

  this3->sense_paths_gplus = List_append(this3->sense_paths_gplus,this3->extended_sense_paths_gplus);
  this3->sense_paths_gminus = List_append(this3->sense_paths_gminus,this3->extended_sense_paths_gminus);
  this3->antisense_paths_gplus = List_append(this3->antisense_paths_gplus,this3->extended_antisense_paths_gplus);
  this3->antisense_paths_gminus = List_append(this3->antisense_paths_gminus,this3->extended_antisense_paths_gminus);
  this3->extended_sense_paths_gplus = (List_T) NULL;
  this3->extended_sense_paths_gminus = (List_T) NULL;
  this3->extended_antisense_paths_gplus = (List_T) NULL;
  this3->extended_antisense_paths_gminus = (List_T) NULL;


  debug(printf("Calling Concordance_simple with unextended paths, sense\n"));
  pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				 /*newpaths5_gplus*/this5->unextended_sense_paths_gplus,
				 /*newpaths5_gminus*/this5->unextended_sense_paths_gminus,
				 /*newpaths3_gplus*/this3->unextended_sense_paths_gplus,
				 /*newpaths3_gminus*/this3->unextended_sense_paths_gminus,
				 
				 this5->sense_paths_gplus,this5->sense_paths_gminus,
				 this3->sense_paths_gplus,this3->sense_paths_gminus,
				 
				 query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				 queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				 this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 
				 novel_diagonals_alloc,localdb_alloc,
				 knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 overall_end_distance_5,overall_end_distance_3,
				 
				 intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				 vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  
  if (splicingp == true) {
    debug(printf("Calling Concordance_simple with unextended paths, antisense\n"));
    pathpairs = Concordance_simple(&found_score_paired,&(*found_score_5),&(*found_score_3),
				   &(*found_transcriptp_5),&(*found_transcriptp_3),pathpairs,

				   /*newpaths5_gplus*/this5->unextended_antisense_paths_gplus,
				   /*newpaths5_gminus*/this5->unextended_antisense_paths_gminus,
				   /*newpaths3_gplus*/this3->unextended_antisense_paths_gplus,
				   /*newpaths3_gminus*/this3->unextended_antisense_paths_gminus,
				   
				   this5->antisense_paths_gplus,this5->antisense_paths_gminus,
				   this3->antisense_paths_gplus,this3->antisense_paths_gminus,
				   
				   query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,
				   queryseq5,queryseq3,
				   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,querylength5,querylength3,
				   this5,this3,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				   
				   novel_diagonals_alloc,localdb_alloc,
				   knownsplicing,knownindels,spliceendsgen5,spliceendsgen3,
				   nmismatches_allowed_5,nmismatches_allowed_3,
				   max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				   overall_end_distance_5,overall_end_distance_3,
				   
				   intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
				   vectorpool,hitlistpool,genestrand,/*require_transcript_intersectp*/false,pass);
  }

  debug(printf("After looking at unextended paths (1), we have %d pathpairs and found scores %d and %d\n",
	       List_length(pathpairs),*found_score_5,*found_score_3));

  if (pathpairs != NULL && found_score_paired <= sufficient_score_paired) {
    debug0(print_pathpairs_contents(pathpairs));
    return pathpairs;
  }


  /* Solves only a small fraction of cases, but helps with accuracy
     and does not seem to affect speed much, perhaps 8% */
  /* 4.  Try paired segment search, and double the values for nmismatches_allowed */
  if (splicingp == false) {
    /* Do not perform segment search for DNA-seq reads */
  } else {
    pathpairs =
      paired_read_segment_search(&found_score_paired,&(*found_score_5),&(*found_score_3),
				 &(*found_transcriptp_5),&(*found_transcriptp_3),
				 &(*last_method_5),&(*last_method_3),

				 pathpairs,this5,this3,repetitive_ef64,queryseq5,queryseq3,

				 queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
				 knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 novel_diagonals_alloc,localdb_alloc,
				 query5_compress_fwd,query5_compress_rev,
				 query3_compress_fwd,query3_compress_rev,
				 /*nmismatches_allowed_5*/2 * nmismatches_allowed_5,
				 /*nmismatches_allowed_3*/2 * nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 genestrand,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
				 overall_end_distance_5,overall_end_distance_3,
				 intlistpool,uintlistpool,univcoordlistpool,listpool,univdiagpool,
				 pathpool,transcriptpool,vectorpool,hitlistpool,
				 spliceendsgen5,spliceendsgen3,pass,
				 sufficient_score_5,sufficient_score_3,sufficient_score_paired);

    debug(printf("After paired segment search, we have %d pathpairs and found scores %d and %d\n",
		 List_length(pathpairs),*found_score_5,*found_score_3));
  }

  debug0(print_pathpairs_contents(pathpairs));
  return pathpairs;
}


static List_T
find_inner_fusions (int *found_score_5, int *found_score_3,

		    List_T local_sense_paths5, List_T local_antisense_paths5,
		    List_T local_sense_paths3, List_T local_antisense_paths3,

		    Shortread_T queryseq5, Shortread_T queryseq3,
		    char *queryuc_ptr_5, char *queryrc5, char *queryuc_ptr_3, char *queryrc3,
		    Knownsplicing_T knownsplicing, Univcoord_T *novel_diagonals_alloc,
		    unsigned short *localdb_alloc, T this5, T this3,

		    Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
		    Compress_T query3_compress_fwd, Compress_T query3_compress_rev,
		    int nmismatches_allowed_5, int nmismatches_allowed_3,
		    int max_insertionlen_5, int max_insertionlen_3, int max_deletionlen_5, int max_deletionlen_3,
		    
		    Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
		    Listpool_T listpool, Pathpool_T pathpool, Vectorpool_T vectorpool,
		    Hitlistpool_T hitlistpool, Transcriptpool_T transcriptpool) {


  List_T pathpairs = NULL, p;
  Path_T path5, path3;


  for (p = local_sense_paths5; p != NULL; p = List_next(p)) {
    path5 = (Path_T) List_head(p);
    if ((path5->plusp == true && Path_unextended_qend_p(path5,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true) ||
	(path5->plusp == false && Path_unextended_qstart_p(path5,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true)) {
      pathpairs = find_inner_fusions_path5(&(*found_score_5),pathpairs,path5,local_sense_paths3,
					   this5,query5_compress_fwd,query5_compress_rev,queryseq5,queryseq3,
					   queryuc_ptr_5,queryrc5,novel_diagonals_alloc,localdb_alloc,
					   knownsplicing,nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
					   intlistpool,uintlistpool,univcoordlistpool,
					   listpool,pathpool,vectorpool,hitlistpool,transcriptpool);

    }
  }

  for (p = local_antisense_paths5; p != NULL; p = List_next(p)) {
    path5 = (Path_T) List_head(p);
    if ((path5->plusp == true && Path_unextended_qend_p(path5,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true) ||
	(path5->plusp == false && Path_unextended_qstart_p(path5,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true)) {
      pathpairs = find_inner_fusions_path5(&(*found_score_5),pathpairs,path5,local_antisense_paths3,
					   this5,query5_compress_fwd,query5_compress_rev,queryseq5,queryseq3,
					   queryuc_ptr_5,queryrc5,novel_diagonals_alloc,localdb_alloc,
					   knownsplicing,nmismatches_allowed_5,max_insertionlen_5,max_deletionlen_5,
					   intlistpool,uintlistpool,univcoordlistpool,
					   listpool,pathpool,vectorpool,hitlistpool,transcriptpool);
    }
  }

  for (p = local_sense_paths3; p != NULL; p = List_next(p)) {
    path3 = (Path_T) List_head(p);
    if ((path3->plusp == true && Path_unextended_qstart_p(path3,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true) ||
	(path3->plusp == false && Path_unextended_qend_p(path3,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true)) {
      pathpairs = find_inner_fusions_path3(&(*found_score_3),pathpairs,path3,local_sense_paths5,
					   this3,query3_compress_fwd,query3_compress_rev,queryseq5,queryseq3,
					   queryuc_ptr_3,queryrc3,novel_diagonals_alloc,localdb_alloc,
					   knownsplicing,nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
					   intlistpool,uintlistpool,univcoordlistpool,
					   listpool,pathpool,vectorpool,
					   hitlistpool,transcriptpool);
    }
  }

  for (p = local_antisense_paths3; p != NULL; p = List_next(p)) {
    path3 = (Path_T) List_head(p);
    if ((path3->plusp == true && Path_unextended_qstart_p(path3,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true) ||
	(path3->plusp == false && Path_unextended_qend_p(path3,/*endtrim_allowed*/8,/*allow_ambig_p*/false) == true)) {
      pathpairs = find_inner_fusions_path3(&(*found_score_3),pathpairs,path3,local_antisense_paths5,
					   this3,query3_compress_fwd,query3_compress_rev,queryseq5,queryseq3,
					   queryuc_ptr_3,queryrc3,novel_diagonals_alloc,localdb_alloc,
					   knownsplicing,nmismatches_allowed_3,max_insertionlen_3,max_deletionlen_3,
					   intlistpool,uintlistpool,univcoordlistpool,
					   listpool,pathpool,vectorpool,
					   hitlistpool,transcriptpool);
    }
  }

  return pathpairs;
}



/* pairtype can be CONCORDANT, CONCORDANT_TRANSLOCATIONS, PAIRED_INVERSION, PAIRED_SCRAMBLE, PAIRED_TOOLONG, UNPAIRED */
static Pairtype_T
determine_pairtype (Path_T path5, Path_T path3) {
  Univcoord_T genomicstart5, genomicend5, genomicstart3, genomicend3;
  Chrpos_T pairmax;

  debug14(printf("Entered determine_pairtype\n"));
  if (path5->chrnum != path3->chrnum) {
    debug14(printf("Returning unpaired because path5 chrnum %d != path3 chrnum %d\n",
		   path5->chrnum,path3->chrnum));
    return UNPAIRED;

  } else if (path5->fusion_querystart_junction != NULL ||
      path5->fusion_queryend_junction != NULL ||
      path3->fusion_querystart_junction != NULL ||
      path3->fusion_queryend_junction != NULL) {
    debug14(printf("Returning translocations\n"));
    /* On the same chromosome, so consider them concordant, but we may need to check their distance */
    return CONCORDANT_TRANSLOCATIONS;

#ifdef TO_FIX
  } else if (Transcript_concordant_p(path5->transcripts_consistent,path3->transcripts_consistent) == true) {
    debug14(printf("Returning concordant based on transcriptome\n"));
    return CONCORDANT;
#endif

  } else if (path5->plusp != path3->plusp) {
    debug14(printf("Returning paired_inversion\n"));
    return PAIRED_INVERSION;

  } else if (path5->plusp == true) {
    genomicstart5 = Path_genomicstart(path5);
    genomicend5 = Path_genomicend(path5);
    genomicstart3 = Path_genomicstart(path3);
    genomicend3 = Path_genomicend(path3);

#ifdef TO_FIX
    if (path5->circularalias == 0 && path3->circularalias == 0) {
      /* Keep coordinates as is */
    } else if (path5->circularalias == 0) {
      if (path3->circularalias == -1) {
	debug14(printf("Have to alias path3\n"));
	assert(circularp[path3->chrnum] == true);
	chrlength = (path3->chrhigh - path3->chroffset)/2;
	genomicstart3 += chrlength;
	genomicend3 += chrlength;
      }
    } else if (path3->circularalias == 0) {
      if (path5->circularalias == +1) {
	debug14(printf("Have to unalias path5\n"));
	assert(circularp[path5->chrnum] == true);
	chrlength = (path5->chrhigh - path5->chroffset)/2;
	genomicstart5 -= chrlength;
	genomicend5 -= chrlength;
      }
    }
#endif

    if (genomicend3 < genomicstart5) {
      debug14(printf("(plus) path3 genomicend %u < path5 genomicstart %u => Returning paired_scramble\n",
		     genomicend3,genomicstart5));
      return PAIRED_SCRAMBLE;
    } else {
      if (circularp[path5->chrnum] == true) {
	pairmax = pairmax_circular;
      } else {
	pairmax = pairmax_linear;
      }

      if (genomicstart3 > genomicend5 + pairmax) {
	debug14(printf("Returning paired_toolong\n"));
	return PAIRED_TOOLONG;
      } else {
	debug14(printf("Returning concordant\n"));
	return CONCORDANT;
      }
    }

  } else {
    genomicstart5 = Path_genomicstart(path5);
    genomicend5 = Path_genomicend(path5);
    genomicstart3 = Path_genomicstart(path3);
    genomicend3 = Path_genomicend(path3);

#ifdef TO_FIX
    if (path5->circularalias == 0 && path3->circularalias == 0) {
      /* Keep coordinates as is */
    } else if (path5->circularalias == 0) {
      if (path3->circularalias == +1) {
	debug14(printf("Have to unalias path3\n"));
	assert(circularp[path3->chrnum] == true);
	chrlength = (path3->chrhigh - path3->chroffset)/2;
	genomicstart3 -= chrlength;
	genomicend3 -= chrlength;
      }
    } else if (path3->circularalias == 0) {
      if (path5->circularalias == -1) {
	debug14(printf("Have to alias path5\n"));
	assert(circularp[path5->chrnum] == true);
	chrlength = (path5->chrhigh - path5->chroffset)/2;
	genomicstart5 += chrlength;
	genomicend5 += chrlength;
      }
    }
#endif

    if (genomicend3 > genomicstart5) {
      debug14(printf("(minus) path3 genomicend %u > path5 genomicstart %u => Returning paired_scramble\n",
		     genomicend3,genomicstart5));
      return PAIRED_SCRAMBLE;
    } else {
      if (circularp[path3->chrnum] == true) {
	pairmax = pairmax_circular;
      } else {
	pairmax = pairmax_linear;
      }

      if (genomicstart3 + pairmax < genomicend5) {
	debug14(printf("Returning paired_toolong\n"));
	return PAIRED_TOOLONG;
      } else {
	debug14(printf("Returning concordant\n"));
	return CONCORDANT;
      }
    }
  }
}


/* Have three lists: pathpairs, samechr, and conc_transloc => result */
/* final_pairtype can be CONCORDANT_TRANSLOCATIONS, CONCORDANT, PAIRED_INVERSION, PAIRED_SCRAMBLE, PAIRED_TOOLONG, UNPAIRED */


static Pathpair_T *
consolidate_results (int *found_score_5, int *found_score_3,
		     bool *found_transcriptp_5, bool *found_transcriptp_3, Pairtype_T *final_pairtype,
		     int *npaths_primary, int *npaths_altloc, int *first_absmq, int *second_absmq,
		     Path_T **patharray5, int *npaths5_primary, int *npaths5_altloc, int *first_absmq5, int *second_absmq5,
		     Path_T **patharray3, int *npaths3_primary, int *npaths3_altloc, int *first_absmq3, int *second_absmq3,

		     List_T pathpairs, List_T sense_paths5, List_T antisense_paths5,
		     List_T sense_paths3, List_T antisense_paths3,

		     Shortread_T queryseq5, Shortread_T queryseq3,
		     char *queryuc_ptr_5, char *queryrc5, int querylength5,
		     char *queryuc_ptr_3, char *queryrc3, int querylength3,

		     Knownsplicing_T knownsplicing, Knownindels_T knownindels,
		     Univcoord_T *novel_diagonals_alloc, unsigned short *localdb_alloc,
		     T this5, T this3,

		     int *mismatch_positions_alloc_5, int *mismatch_positions_alloc_3,

		     Compress_T query5_compress_fwd, Compress_T query5_compress_rev,
		     Compress_T query3_compress_fwd, Compress_T query3_compress_rev,

		     int nmismatches_allowed_5, int nmismatches_allowed_3,
		     int nmismatches_filter_5, int nmismatches_filter_3,
		     int mincoverage_filter_5, int mincoverage_filter_3,
		     int max_insertionlen_5, int max_insertionlen_3,
		     int max_deletionlen_5, int max_deletionlen_3,
		     int overall_end_distance_5, int overall_end_distance_3,
		
		     Intlistpool_T intlistpool, Uintlistpool_T uintlistpool, Univcoordlistpool_T univcoordlistpool,
		     Listpool_T listpool, Univdiagpool_T univdiagpool,
		     Pathpool_T pathpool, Vectorpool_T vectorpool,
		     Hitlistpool_T hitlistpool, Transcriptpool_T transcriptpool,
		     Spliceendsgen_T spliceendsgen5, Spliceendsgen_T spliceendsgen3, Pass_T pass) {

  Pathpair_T *pathpairarray, pathpair;
  List_T newpaths, singlepaths5, singlepaths3, paths5, paths3, p, q;
  Path_T path, path5, path3, copy;
  Compress_T query_compress;
  char *queryptr;
  bool completep;
  int sensedir5, sensedir3;
  int tr_insertlength;
  int i, j;

  *npaths5_primary = *npaths5_altloc = 0;
  *npaths3_primary = *npaths3_altloc = 0;
  *patharray5 = (Path_T *) NULL;
  *patharray3 = (Path_T *) NULL;

  if (pathpairs == NULL) {
    debug(printf("pathpairs is NULL, so handling unpaired ends\n"));
    /* Unpaired ends */
    if (sense_paths5 != NULL && antisense_paths5 == NULL) {
      sensedir5 = SENSE_FORWARD;
    } else if (sense_paths5 == NULL && antisense_paths5 != NULL) {
      sensedir5 = SENSE_ANTI;
    } else {
      sensedir5 = SENSE_NULL;
    }
	
    if (sense_paths3 != NULL && antisense_paths3 == NULL) {
      sensedir3 = SENSE_FORWARD;
    } else if (sense_paths3 == NULL && antisense_paths3 != NULL) {
      sensedir3 = SENSE_ANTI;
    } else {
      sensedir3 = SENSE_NULL;
    }

    if (sensedir5 == SENSE_NULL && sensedir3 == SENSE_NULL) {
      /* No restriction */
      paths5 = List_append(sense_paths5,antisense_paths5);
      paths3 = List_append(sense_paths3,antisense_paths3);
    } else if (sensedir5 == SENSE_FORWARD && sensedir3 == SENSE_ANTI) {
      /* Contradiction */
      paths5 = List_append(sense_paths5,antisense_paths5);
      paths3 = List_append(sense_paths3,antisense_paths3);
    } else if (sensedir5 == SENSE_ANTI && sensedir3 == SENSE_FORWARD) {
      /* Contradiction */
      paths5 = List_append(sense_paths5,antisense_paths5);
      paths3 = List_append(sense_paths3,antisense_paths3);
    } else if (sensedir5 == SENSE_FORWARD || sensedir3 == SENSE_FORWARD) {
      /* Restrict to sense */
      paths5 = sense_paths5;
      paths3 = sense_paths3;
    } else if (sensedir5 == SENSE_ANTI || sensedir3 == SENSE_ANTI) {
      /* Restrict to antisense */
      paths5 = antisense_paths5;
      paths3 = antisense_paths3;
    } else {
      fprintf(stderr,"Unexpected combination of sensedirs\n");
      abort();
    }

    singlepaths5 = (List_T) NULL;
    for (p = paths5; p != NULL; p = List_next(p)) {
      path = (Path_T) List_head(p);
      if (path->plusp == true) {
	queryptr = queryuc_ptr_5;
	query_compress = query5_compress_fwd;
      } else {
	queryptr = queryrc5;
	query_compress = query5_compress_rev;
      }
      /* Need to call Path_extend primarily for the trimming, which can weed out false alignments past the end of the chromosome,
	 but might as well extend also if possible */
      if (path->transcriptome_method_p == true) {
	copy = Path_copy(path,intlistpool,univcoordlistpool,listpool,
			 pathpool,vectorpool,transcriptpool);
	singlepaths5 = Hitlist_push(singlepaths5,hitlistpool,(void *) copy
				    hitlistpool_trace(__FILE__,__LINE__));
      } else {
	newpaths = Path_extend(&completep,&(*found_score_5),&(*found_transcriptp_5),
			       /*original_path*/path,queryseq5,queryptr,querylength5,
			       mismatch_positions_alloc_5,novel_diagonals_alloc,localdb_alloc,
			       this5->streamspace_max_alloc,this5->streamspace_alloc,
			       this5->streamptr_alloc,this5->streamsize_alloc,this5->mergeinfo,
			       this5->indelinfo,this5->spliceinfo,knownsplicing,knownindels,
			       query_compress,query5_compress_fwd,query5_compress_rev,
			       /*genestrand*/0,max_insertionlen_5,max_deletionlen_5,overall_end_distance_5,nmismatches_allowed_5,
			       /*paired_end_p*/false,/*lowp*/true,
			       intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
			       vectorpool,hitlistpool,spliceendsgen5,pass,
			       /*extend_qstart_p*/true,/*extend_qend_p*/true);
	for (q = newpaths; q != NULL; q = List_next(q)) {
	  path = (Path_T) List_head(q);
	  Path_eval_nmatches(&(*found_score_5),path,query5_compress_fwd,query5_compress_rev);
	  singlepaths5 = Hitlist_push(singlepaths5,hitlistpool,(void *) path
				      hitlistpool_trace(__FILE__,__LINE__));
	}
	Hitlistpool_free_list(&newpaths,hitlistpool
			      hitlistpool_trace(__FILE__,__LINE__)); /* Allocated by Hitlistpool_T */
      }
    }
    Hitlistpool_free_list(&paths5,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));


    singlepaths3 = (List_T) NULL;
    for (p = paths3; p != NULL; p = List_next(p)) {
      path = (Path_T) List_head(p);
      if (path->plusp == true) {
	queryptr = queryuc_ptr_3;
	query_compress = query3_compress_fwd;
      } else {
	queryptr = queryrc3;
	query_compress = query3_compress_rev;
      }
      /* Need to call Path_extend primarily for the trimming, which can weed out false alignments past the end of the chromosome,
	 but might as well extend also if possible */
      if (path->transcriptome_method_p == true) {
	copy = Path_copy(path,intlistpool,univcoordlistpool,listpool,
			 pathpool,vectorpool,transcriptpool);
	singlepaths3 = Hitlist_push(singlepaths3,hitlistpool,(void *) copy
				    hitlistpool_trace(__FILE__,__LINE__));
      } else {
	newpaths = Path_extend(&completep,&(*found_score_3),&(*found_transcriptp_3),
			       /*original_path*/path,queryseq3,queryptr,querylength3,
			       mismatch_positions_alloc_3,novel_diagonals_alloc,localdb_alloc,
			       this3->streamspace_max_alloc,this3->streamspace_alloc,
			       this3->streamptr_alloc,this3->streamsize_alloc,this3->mergeinfo,
			       this3->indelinfo,this3->spliceinfo,knownsplicing,knownindels,
			       query_compress,query3_compress_fwd,query3_compress_rev,
			       /*genestrand*/0,max_insertionlen_3,max_deletionlen_3,overall_end_distance_3,nmismatches_allowed_3,
			       /*paired_end_p*/false,/*lowp*/true,
			       intlistpool,uintlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,
			       vectorpool,hitlistpool,spliceendsgen3,pass,
			       /*extend_qstart_p*/true,/*extend_qend_p*/true);
	for (q = newpaths; q != NULL; q = List_next(q)) {
	  path = (Path_T) List_head(q);
	  Path_eval_nmatches(&(*found_score_3),path,query3_compress_fwd,query3_compress_rev);
	  singlepaths3 = Hitlist_push(singlepaths3,hitlistpool,(void *) path
				      hitlistpool_trace(__FILE__,__LINE__));
	}
	Hitlistpool_free_list(&newpaths,hitlistpool
			      hitlistpool_trace(__FILE__,__LINE__)); /* Allocated by Hitlistpool_T */
      }
    }
    Hitlistpool_free_list(&paths3,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));

    if (singlepaths5 == (List_T) NULL) {
      *npaths5_primary = *npaths5_altloc = 0;
      *patharray5 = (Path_T *) NULL;
    } else {
      *patharray5 = (Path_T *) List_to_array_out(singlepaths5,NULL); /* Return value */
      *patharray5 = Path_eval_and_sort(&(*npaths5_primary),&(*npaths5_altloc),&(*first_absmq5),&(*second_absmq5),
				       *patharray5,List_length(singlepaths5),
				       query5_compress_fwd,query5_compress_rev,queryuc_ptr_5,queryrc5,
				       Shortread_quality_string(queryseq5),
				       nmismatches_filter_5,mincoverage_filter_5,
				       intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool);

      if (transcriptome != NULL && pass == PASS2) {
	for (i = 0; i < (*npaths5_primary) + (*npaths5_altloc); i++) {
	  path = (*patharray5)[i];
	  Transcript_velocity_single(path);
	}
      }

      Hitlistpool_free_list(&singlepaths5,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
    }

    if (singlepaths3 == (List_T) NULL) {
      *npaths3_primary = *npaths3_altloc = 0;
      *patharray3 = (Path_T *) NULL;
    } else {
      *patharray3 = (Path_T *) List_to_array_out(singlepaths3,NULL); /* Return value */
      *patharray3 = Path_eval_and_sort(&(*npaths3_primary),&(*npaths3_altloc),&(*first_absmq3),&(*second_absmq3),
				       *patharray3,List_length(singlepaths3),
				       query3_compress_fwd,query3_compress_rev,queryuc_ptr_3,queryrc3,
				       Shortread_quality_string(queryseq3),
				       nmismatches_filter_3,mincoverage_filter_3,
				       intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool);

      if (transcriptome != NULL && pass == PASS2) {
	for (i = 0; i < (*npaths3_primary) + (*npaths3_altloc); i++) {
	  path = (*patharray3)[i];
	  Transcript_velocity_single(path);
	}
      }

      Hitlistpool_free_list(&singlepaths3,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
    }

    debug(printf("For single paths5, got %d+%d paths\n",*npaths5_primary,*npaths5_altloc));
    debug(printf("For single paths3, got %d+%d paths\n",*npaths3_primary,*npaths3_altloc));

    /* Check for concordance */
    assert(pathpairs == NULL);
    for (i = 0; i < *npaths5_primary + *npaths5_altloc; i++) {
      path5 = (*patharray5)[i];
      for (j = 0; j < *npaths3_primary + *npaths3_altloc; j++) {
	path3 = (*patharray3)[j];
	if (determine_pairtype(path5,path3) != CONCORDANT) {
	  /* Skip */
	} else if (path5->plusp == true) {
	  if ((pathpair = Pathpair_new_concordant(/*pathL*/path5,/*pathH*/path3,
						  /*queryseqL*/queryseq5,/*queryseqH*/queryseq3,/*plusp*/true,
						  intlistpool,univcoordlistpool,
						  listpool,pathpool,vectorpool,transcriptpool,
						  /*copyLp*/true,/*copyHp*/true)) != NULL) {
	    debug16(printf("Found a concordant pair, gplus\n"));
	    pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				     hitlistpool_trace(__FILE__,__LINE__));
	    debug16(Path_print(pathpair->path5));
	    debug16(Path_print(pathpair->path3));
	  }
	} else {
	  if ((pathpair = Pathpair_new_concordant(/*pathL*/path3,/*pathH*/path5,
						  /*queryseqL*/queryseq3,/*queryseqH*/queryseq5,/*plusp*/false,
						  intlistpool,univcoordlistpool,
						  listpool,pathpool,vectorpool,transcriptpool,
						  /*copyLp*/true,/*copyHp*/true)) != NULL) {
	    debug16(printf("Found a concordant pair, gminus\n"));
	    pathpairs = Hitlist_push(pathpairs,hitlistpool,(void *) pathpair
				     hitlistpool_trace(__FILE__,__LINE__));
	    debug16(Path_print(pathpair->path5));
	    debug16(Path_print(pathpair->path3));
	  }
	}
      }
    }
  }

  if (pathpairs == NULL) {
    *npaths_primary = *npaths_altloc = 0;

  } else {
    /* Don't want to filter here, since Pathpair_eval_and_sort needs to keep both sensedirs and perform resolve */
    /* pathpairs = Pathpair_filter(pathpairs,
       intlistpool,univcoordlistpool,listpool,pathpool,hitlistpool); */

    *npaths_primary = List_length(pathpairs);
    *npaths_altloc = 0;	/* TODO: Determine whether any paths are on the altloc chromosome */

    pathpairarray = (Pathpair_T *) List_to_array_out(pathpairs,NULL);
    pathpairarray = Pathpair_eval_and_sort(&(*found_score_5),&(*found_score_3),
					   &(*npaths_primary),&(*npaths_altloc),&(*first_absmq),&(*second_absmq),
					   pathpairarray,/*npaths*/List_length(pathpairs),this5,this3,
					   query5_compress_fwd,query5_compress_rev,
					   query3_compress_fwd,query3_compress_rev,
					   queryseq5,queryseq3,
					   queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,
					   /*quality_string_5*/Shortread_quality_string(queryseq5),
					   /*quality_string_3*/Shortread_quality_string(queryseq3),
					   novel_diagonals_alloc,localdb_alloc,knownsplicing,

					   nmismatches_allowed_5,nmismatches_allowed_3,
					   nmismatches_filter_5,nmismatches_filter_3,
					   mincoverage_filter_5,mincoverage_filter_3,
					   max_insertionlen_5,max_insertionlen_3,
					   max_deletionlen_5,max_deletionlen_3,querylength5,querylength3,
					   univdiagpool,intlistpool,uintlistpool,univcoordlistpool,
					   listpool,pathpool,transcriptpool,vectorpool,hitlistpool);

    /* Compute transcripts for pass2 */
    if (transcriptome != NULL && pass == PASS2) {
      for (i = 0; i < (*npaths_primary) + (*npaths_altloc); i++) {
	pathpair = pathpairarray[i];
	path5 = pathpair->path5;
	path3 = pathpair->path3;

	Transcript_velocity_paired(path5,path3);
	if ((tr_insertlength = Transcript_fragment_length(path5,path3,queryseq5,queryseq3)) > 0) {
	  pathpair->insertlength = tr_insertlength;
	}
      }
    }

    Hitlistpool_free_list(&pathpairs,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));  /* Allocated by hitlistpool */

    debug(printf("After Pathpair_eval_and_sort, have %d + %d pathpairs\n",
		 *npaths_primary,*npaths_altloc));
  }

  if ((*npaths_primary) + (*npaths_altloc) > 0) {
    *final_pairtype = CONCORDANT;
    debug(printf("Success in finding pathpairs, so clearing single paths\n"));
    for (i = 0; i < *npaths5_primary + *npaths5_altloc; i++) {
      path5 = (*patharray5)[i];
      Path_free(&path5,intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool);
    }
    *npaths5_primary = *npaths5_altloc = 0;
    FREE_OUT(*patharray5);
    
    for (i = 0; i < *npaths3_primary + *npaths3_altloc; i++) {
      path3 = (*patharray3)[i];
      Path_free(&path3,intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool);
    }
    *npaths3_primary = *npaths3_altloc = 0;
    FREE_OUT(*patharray3);

    *patharray5 = *patharray3 = (Path_T *) NULL;
    debug(printf("(1) Returning %d %d %d\n",*npaths_primary,*npaths5_primary,*npaths3_primary));

  } else if (*npaths5_primary != 1 || *npaths3_primary != 1) {
    *final_pairtype = UNPAIRED;
    *npaths_primary = *npaths_altloc = 0;
    pathpairarray = (Pathpair_T *) NULL;
    debug(printf("(2) Returning %d %d %d\n",*npaths_primary,*npaths5_primary,*npaths3_primary));

  } else {
    *final_pairtype = determine_pairtype((*patharray5)[0],(*patharray3)[0]);
    *npaths_primary = *npaths_altloc = 0;
    pathpairarray = (Pathpair_T *) NULL;
    debug(printf("(3) Returning %d %d %d\n",*npaths_primary,*npaths5_primary,*npaths3_primary));
  }

  return pathpairarray;
}

#ifdef DEBUG0
static void
print_pathpairarray_contents (Pathpair_T *pathpairarray, int n) {
  int i;

  for (i = 0; i < n; i++) {
    printf("%p %p pathpairarray\n",pathpairarray[i]->path5,pathpairarray[i]->path3);
  }

  return;
}
#endif




/* final_pairtype can be CONCORDANT_TRANSLOCATIONS, CONCORDANT, PAIRED_INVERSION, PAIRED_SCRAMBLE, PAIRED_TOOLONG, UNPAIRED */
Pathpair_T *
Stage1_paired_read (int *npaths_primary, int *npaths_altloc, int *first_absmq, int *second_absmq, Pairtype_T *final_pairtype,
		    Path_T **patharray5, int *npaths5_primary, int *npaths5_altloc, int *first_absmq5, int *second_absmq5,
		    Path_T **patharray3, int *npaths3_primary, int *npaths3_altloc, int *first_absmq3, int *second_absmq3,
		    Shortread_T queryseq5, Shortread_T queryseq3, EF64_T repetitive_ef64,
		    Knownsplicing_T knownsplicing, Knownindels_T knownindels, Chrpos_T pairmax_linear,
		    Trdiagpool_T trdiagpool, Univdiagpool_T univdiagpool,
		    Intlistpool_T intlistpool, Uintlistpool_T uintlistpool,
		    Univcoordlistpool_T univcoordlistpool, Listpool_T listpool, 
		    Trpathpool_T trpathpool, Pathpool_T pathpool, Vectorpool_T vectorpool, Hitlistpool_T hitlistpool,
		    Transcriptpool_T transcriptpool,
		    Spliceendsgen_T spliceendsgen5, Spliceendsgen_T spliceendsgen3, Pass_T pass) {
  Pathpair_T *pathpairarray;
  List_T pathpairs;
  List_T sense_paths5 = NULL, antisense_paths5 = NULL, sense_paths3 = NULL, antisense_paths3 = NULL;
  List_T local_sense_paths5, local_antisense_paths5, local_sense_paths3, local_antisense_paths3, paths5, paths3;

  /* List_T geneplus_pathpairs, geneminus_pathpairs; */
  /* List_T geneplus_paths5, geneplus_paths3, geneminus_paths5, geneminus_paths3; */

  int querylength5, querylength3;
  bool found_transcriptp_5, found_transcriptp_3;

  int found_score_5, found_score_3;
  Method_T last_method_5 = METHOD_INIT, last_method_3 = METHOD_INIT;
  int sufficient_score_5, sufficient_score_3;

  int nmismatches_filter_5, nmismatches_filter_3;
  int mincoverage_filter_5, mincoverage_filter_3;
  int nmismatches_allowed_5, nmismatches_allowed_3;
  int max_middle_insertions_5, max_middle_insertions_3, max_middle_deletions_5, max_middle_deletions_3;
  int max_insertionlen_5, max_insertionlen_3, max_deletionlen_5, max_deletionlen_3;
  Chrpos_T overall_max_distance_5, overall_max_distance_3, overall_end_distance_5, overall_end_distance_3;
  char *queryuc_ptr_5, *queryuc_ptr_3, *queryrc5, *queryrc3;
  int *mismatch_positions_alloc_5, *mismatch_positions_alloc_3;
  Univcoord_T *novel_diagonals_alloc;
  unsigned short *localdb_alloc;
  Compress_T query5_compress_fwd, query5_compress_rev, query3_compress_fwd, query3_compress_rev;
  T this5, this3;


  querylength5 = Shortread_fulllength(queryseq5);
  querylength3 = Shortread_fulllength(queryseq3);

  queryuc_ptr_5 = Shortread_queryuc_ptr(queryseq5);
  queryuc_ptr_3 = Shortread_queryuc_ptr(queryseq3);
  queryrc5 = Shortread_queryrc(queryseq5);
  queryrc3 = Shortread_queryrc(queryseq3);

  this5 = Stage1_new(queryuc_ptr_5,querylength5);
  this3 = Stage1_new(queryuc_ptr_3,querylength3);

  found_score_5 = querylength5;
  found_score_3 = querylength3;

  sufficient_score_5 = (int) rint(defect_rate * (double) querylength5);
  sufficient_score_3 = (int) rint(defect_rate * (double) querylength3);

  /* nmismatches_allowed means nmismatches_search and is not specified
     by the user.  The user-specified value for -m represents
     nmismatches_filter */
  /* TODO: make this dependent upon the defect rate */
  nmismatches_allowed_5 = querylength5/20; /* was querylength/index1part */
  nmismatches_allowed_3 = querylength3/20; /* was querylength/index1part */

  if (user_nmismatches_filter_float < 0.0) {
    /* Not specified, so don't filter */
    nmismatches_filter_5 = querylength5;
    nmismatches_filter_3 = querylength3;
  } else if (user_nmismatches_filter_float < 1.0) {
    nmismatches_filter_5 = (int) rint(user_nmismatches_filter_float * (double) querylength5);
    nmismatches_filter_3 = (int) rint(user_nmismatches_filter_float * (double) querylength3);
  } else {
    nmismatches_filter_5 = nmismatches_filter_3 = (int) user_nmismatches_filter_float;
  }

  if (user_mincoverage_filter_float <= 0.0) {
    /* Not specified, so don't filter */
    mincoverage_filter_5 = 0;
    mincoverage_filter_3 = 0;
  } else if (user_mincoverage_filter_float <= 1.0) {
    /* Assuming that --min-coverage=1 must mean 1.0 and not a coverage of 1 bp */
    mincoverage_filter_5 = (int) rint(user_mincoverage_filter_float * (double) querylength5);
    mincoverage_filter_3 = (int) rint(user_mincoverage_filter_float * (double) querylength3);
  } else {
    mincoverage_filter_5 = mincoverage_filter_3 = (int) user_mincoverage_filter_float;
  }

  if (max_middle_insertions_float > 0.0 && max_middle_insertions_float < 1.0) {
    max_middle_insertions_5 = (int) rint(max_middle_insertions_float * (double) querylength5);
    max_middle_insertions_3 = (int) rint(max_middle_insertions_float * (double) querylength3);
  } else {
    max_middle_insertions_5 = max_middle_insertions_3 = (int) max_middle_insertions_float;
  }
  max_insertionlen_5 = max_middle_insertions_5;
  if (max_insertionlen_5 > querylength5) {
    max_insertionlen_5 = querylength5;
  }
  max_insertionlen_3 = max_middle_insertions_3;
  if (max_insertionlen_3 > querylength3) {
    max_insertionlen_3 = querylength3;
  }


  if (max_middle_deletions_float > 0.0 && max_middle_deletions_float < 1.0) {
    max_middle_deletions_5 = (int) rint(max_middle_deletions_float * (double) querylength5);
    max_middle_deletions_3 = (int) rint(max_middle_deletions_float * (double) querylength3);
  } else {
    max_middle_deletions_5 = max_middle_insertions_3 = (int) max_middle_deletions_float;
  }
  max_deletionlen_5 = max_middle_deletions_5;
  max_deletionlen_3 = max_middle_deletions_3;

  overall_max_distance_5 = shortsplicedist;
  if ((Chrpos_T) max_middle_deletions_5 > overall_max_distance_5) {
    overall_max_distance_5 = (Chrpos_T) max_middle_deletions_5;
  }
  if ((Chrpos_T) max_middle_insertions_5 > overall_max_distance_5) {
    overall_max_distance_5 = (Chrpos_T) max_middle_insertions_5;
  }
  overall_end_distance_5 = shortsplicedist_novelend > (Chrpos_T) max_deletionlen_5 ? shortsplicedist_novelend : (Chrpos_T) max_deletionlen_5;

  overall_max_distance_3 = shortsplicedist;
  if ((Chrpos_T) max_middle_deletions_3 > overall_max_distance_3) {
    overall_max_distance_3 = (Chrpos_T) max_middle_deletions_3;
  }
  if ((Chrpos_T) max_middle_insertions_3 > overall_max_distance_3) {
    overall_max_distance_3 = (Chrpos_T) max_middle_insertions_3;
  }
  overall_end_distance_3 = shortsplicedist_novelend > (Chrpos_T) max_deletionlen_3 ? shortsplicedist_novelend : (Chrpos_T) max_deletionlen_3;


  mismatch_positions_alloc_5 = (int *) MALLOC((querylength5+MISMATCH_EXTRA)*sizeof(int));
  mismatch_positions_alloc_3 = (int *) MALLOC((querylength3+MISMATCH_EXTRA)*sizeof(int));

  /* 2 localdb regions possible if shortsplicedist_novelend < 65536 */
  /* 65536 represents the worst possible case where every position in the localdb region matches the query */
  novel_diagonals_alloc = (Univcoord_T *) MALLOC(2 * 65536 * sizeof(Univcoord_T));
  MALLOC_ALIGN(localdb_alloc,65536 * sizeof(unsigned short)); /* Maximum number of intersections in a localdb region */

  query5_compress_fwd = Compress_new_fwd(queryuc_ptr_5,querylength5);
  query5_compress_rev = Compress_new_rev(queryuc_ptr_5,querylength5);
  query3_compress_fwd = Compress_new_fwd(queryuc_ptr_3,querylength3);
  query3_compress_rev = Compress_new_rev(queryuc_ptr_3,querylength3);


  if (mode == STANDARD || mode == CMET_STRANDED || mode == ATOI_STRANDED || mode == TTOC_STRANDED) {
    if ((pathpairs = paired_read(&found_score_5,&found_score_3,
				 &found_transcriptp_5,&found_transcriptp_3,
				 &last_method_5,&last_method_3,queryseq5,queryseq3,
				 queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
				 knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				 novel_diagonals_alloc,localdb_alloc,this5,this3,repetitive_ef64,
				 query5_compress_fwd,query5_compress_rev,
				 query3_compress_fwd,query3_compress_rev,
				 nmismatches_allowed_5,nmismatches_allowed_3,
				 max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				 /*genestrand*/0,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
				 overall_end_distance_5,overall_end_distance_3,

				 trdiagpool,univdiagpool,intlistpool,uintlistpool,univcoordlistpool,listpool,
				 trpathpool,pathpool,transcriptpool,vectorpool,hitlistpool,
				 spliceendsgen5,spliceendsgen3,pass,
				 sufficient_score_5,sufficient_score_3)) != NULL) {
      local_sense_paths5 = local_antisense_paths5 = (List_T) NULL;
      local_sense_paths3 = local_antisense_paths3 = (List_T) NULL;

    } else {
      /* Gather all single paths.  Combine so that sensedirs can compete. */
      if (this5 == NULL) {
	local_sense_paths5 = local_antisense_paths5 = (List_T) NULL;
      } else {
	paths5 = List_append(Hitlist_copy(this5->sense_paths_gplus,hitlistpool),
			     Hitlist_copy(this5->sense_paths_gminus,hitlistpool));
	paths5 = List_append(Hitlist_copy(this5->antisense_paths_gplus,hitlistpool),paths5);
	paths5 = List_append(Hitlist_copy(this5->antisense_paths_gminus,hitlistpool),paths5);
	paths5 = List_append(Hitlist_copy(this5->unextended_sense_paths_gplus,hitlistpool),paths5);
	paths5 = List_append(Hitlist_copy(this5->unextended_sense_paths_gminus,hitlistpool),paths5);
	paths5 = List_append(Hitlist_copy(this5->unextended_antisense_paths_gplus,hitlistpool),paths5);
	paths5 = List_append(Hitlist_copy(this5->unextended_antisense_paths_gminus,hitlistpool),paths5);
	Path_local_pick_sensedir(&local_sense_paths5,&local_antisense_paths5,paths5,hitlistpool);
	/* Above function frees paths5 */
      }

      if (this3 == NULL) {
	local_sense_paths3 = local_antisense_paths3 = (List_T) NULL;
      } else {
	paths3 = List_append(Hitlist_copy(this3->sense_paths_gplus,hitlistpool),
			     Hitlist_copy(this3->sense_paths_gminus,hitlistpool));
	paths3 = List_append(Hitlist_copy(this3->antisense_paths_gplus,hitlistpool),paths3);
	paths3 = List_append(Hitlist_copy(this3->antisense_paths_gminus,hitlistpool),paths3);
	paths3 = List_append(Hitlist_copy(this3->unextended_sense_paths_gplus,hitlistpool),paths3);
	paths3 = List_append(Hitlist_copy(this3->unextended_sense_paths_gminus,hitlistpool),paths3);
	paths3 = List_append(Hitlist_copy(this3->unextended_antisense_paths_gplus,hitlistpool),paths3);
	paths3 = List_append(Hitlist_copy(this3->unextended_antisense_paths_gminus,hitlistpool),paths3);
	Path_local_pick_sensedir(&local_sense_paths3,&local_antisense_paths3,paths3,hitlistpool);
	/* Above function frees paths3 */
      }

      /* Then separate locally to find winning sensedirs */
      /* printf("Have %d sense paths5 and %d antisense paths5\n",List_length(sense_paths5),List_length(antisense_paths5));*/
      /* printf("Have %d sense paths3 and %d antisense paths3\n",List_length(sense_paths3),List_length(antisense_paths3)); */

      if (splicingp == true && this5 != NULL && this3 != NULL) {
	/* Inner path fusions require further work */
	pathpairs = find_inner_fusions(&found_score_5,&found_score_3,

				       local_sense_paths5,local_antisense_paths5,
				       local_sense_paths3,local_antisense_paths3,
				       queryseq5,queryseq3,queryuc_ptr_5,queryrc5,queryuc_ptr_3,queryrc3,
				       knownsplicing,novel_diagonals_alloc,localdb_alloc,this5,this3,
				       query5_compress_fwd,query5_compress_rev,
				       query3_compress_fwd,query3_compress_rev,
				       nmismatches_allowed_5,nmismatches_allowed_3,
				       max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,

				       intlistpool,uintlistpool,univcoordlistpool,listpool,
				       pathpool,vectorpool,hitlistpool,transcriptpool);
      }
    }

    /* This call to Pathpair_filter can favor incorrect splices, so need to look at splice probs */
    debug0(printf("Have %d pathpairs before filtering\n",List_length(pathpairs)));
    debug0(print_pathpairs_contents(pathpairs));
    pathpairs = Pathpair_filter(pathpairs,
				intlistpool,univcoordlistpool,listpool,pathpool,transcriptpool,hitlistpool);
    debug0(printf("Have %d pathpairs after filtering\n",List_length(pathpairs)));
    debug0(print_pathpairs_contents(pathpairs));

    /* local paths are a subset of the paths in this5 and this3 */
    if (pathpairs != NULL) {
      Hitlistpool_free_list(&local_sense_paths5,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
      Hitlistpool_free_list(&local_sense_paths3,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
      Hitlistpool_free_list(&local_antisense_paths5,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
      Hitlistpool_free_list(&local_antisense_paths3,hitlistpool
			    hitlistpool_trace(__FILE__,__LINE__));
      sense_paths5 = sense_paths3 = antisense_paths5 = antisense_paths3 = (List_T) NULL;

    } else {
      /* Unpaired paths */
      paths5 = List_append(local_sense_paths5,local_antisense_paths5);
      paths3 = List_append(local_sense_paths3,local_antisense_paths3);

      Path_filter_pick_sensedir(&sense_paths5,&antisense_paths5,paths5,hitlistpool);
      Path_filter_pick_sensedir(&sense_paths3,&antisense_paths3,paths3,hitlistpool);
      /* Above functions free paths5 and paths3 */
    }

    /* sense_paths are a subset of the paths in this5 and this3 */

    pathpairarray =
      consolidate_results(&found_score_5,&found_score_3,
			  &found_transcriptp_5,&found_transcriptp_3,&(*final_pairtype),
			  &(*npaths_primary),&(*npaths_altloc),&(*first_absmq),&(*second_absmq),
			  &(*patharray5),&(*npaths5_primary),&(*npaths5_altloc),&(*first_absmq5),&(*second_absmq5),
			  &(*patharray3),&(*npaths3_primary),&(*npaths3_altloc),&(*first_absmq3),&(*second_absmq3),
			  pathpairs,sense_paths5,antisense_paths5,sense_paths3,antisense_paths3,
				 
			  queryseq5,queryseq3,
			  queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,

			  knownsplicing,knownindels,novel_diagonals_alloc,localdb_alloc,this5,this3,
			  mismatch_positions_alloc_5,mismatch_positions_alloc_3,
			  query5_compress_fwd,query5_compress_rev,query3_compress_fwd,query3_compress_rev,

			  nmismatches_allowed_5,nmismatches_allowed_3,
			  nmismatches_filter_5,nmismatches_filter_3,mincoverage_filter_5,mincoverage_filter_3,
			  max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
			  overall_end_distance_5,overall_end_distance_3,

			  intlistpool,uintlistpool,univcoordlistpool,listpool,univdiagpool,pathpool,vectorpool,
			  hitlistpool,transcriptpool,spliceendsgen5,spliceendsgen3,pass);

    Hitlistpool_free_list(&sense_paths5,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));
    Hitlistpool_free_list(&sense_paths3,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));
    Hitlistpool_free_list(&antisense_paths5,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));
    Hitlistpool_free_list(&antisense_paths3,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));
    
    Hitlistpool_free_list(&pathpairs,hitlistpool
			  hitlistpool_trace(__FILE__,__LINE__));

  } else if (mode == CMET_NONSTRANDED || mode == ATOI_NONSTRANDED || mode == TTOC_NONSTRANDED) {
    pathpairarray = (Pathpair_T *) NULL;
#ifdef TO_FIX
    geneplus_pathpairs = paired_read(&geneplus_abort_pairing_p,&geneplus_hits5,&geneplus_hits3,
				     &geneplus_samechr,&geneplus_conc_transloc,
				     queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
				     knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				     novel_diagonals_alloc,localdb_alloc,this5,this3,
				     query5_compress_fwd,query5_compress_rev,
				     query3_compress_fwd,query3_compress_rev,
				     max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				     /*genestrand*/+1,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
				     overall_end_distance_5,overall_end_distance_3,
				     max_mismatches_refalt_5,max_mismatches_refalt_3,
				     max_mismatches_ref_5,max_mismatches_ref_3,
				     min_coverage_5,min_coverage_3,
				     intlistpool,univcoordlistpool,listpool,univdiagpool,
				     hitlistpool,pathpool,vectorpool,
				     transcriptpool,spliceendsgen5,spliceendsgen3,pass);

    geneminus_pathpairs = paired_read(&geneminus_abort_pairing_p,&geneminus_hits5,&geneminus_hits3,
				      &geneminus_samechr,&geneminus_conc_transloc,
				      queryuc_ptr_5,queryrc5,querylength5,queryuc_ptr_3,queryrc3,querylength3,
				      knownsplicing,knownindels,mismatch_positions_alloc_5,mismatch_positions_alloc_3,
				      novel_diagonals_alloc,localdb_alloc,this5,this3,
				      query5_compress_fwd,query5_compress_rev,
				      query3_compress_fwd,query3_compress_rev,
				      max_insertionlen_5,max_insertionlen_3,max_deletionlen_5,max_deletionlen_3,
				      /*genestrand*/+2,pairmax_linear,overall_max_distance_5,overall_max_distance_3,
				      overall_end_distance_5,overall_end_distance_3,
				      max_mismatches_refalt_5,max_mismatches_refalt_3,
				      max_mismatches_ref_5,max_mismatches_ref_3,
				      min_coverage_5,min_coverage_3,
				      intlistpool,univcoordlistpool,listpool,univdiagpool,
				      hitlistpool,pathpool,vectorpool,
				      transcriptpool,spliceendsgen5,spliceendsgen3,pass);
#endif

  } else {
    fprintf(stderr,"Do not recognize mode %d\n",mode);
    abort();
  }

  Compress_free(&query3_compress_rev);
  Compress_free(&query3_compress_fwd);
  Compress_free(&query5_compress_rev);
  Compress_free(&query5_compress_fwd);

  FREE_ALIGN(localdb_alloc);
  FREE(novel_diagonals_alloc);

  FREE(mismatch_positions_alloc_3);
  FREE(mismatch_positions_alloc_5);

  Stage1_free(&this3,trdiagpool,univdiagpool,intlistpool,uintlistpool,
	      univcoordlistpool,listpool,pathpool,trpathpool,
	      transcriptpool,hitlistpool,/*free_paths_p*/true);
  Stage1_free(&this5,trdiagpool,univdiagpool,intlistpool,uintlistpool,
	      univcoordlistpool,listpool,pathpool,trpathpool,
	      transcriptpool,hitlistpool,/*free_paths_p*/true);

  /* FREE(queryrc3); -- Taken from Shortread */
  /* FREE(queryrc5); -- Taken from Shortread */

  debug(printf("Returning with final_pairtype %s\n",Pairtype_string(*final_pairtype)));
  debug0(print_pathpairarray_contents(pathpairarray,/*n*/(*npaths_primary) + (*npaths_altloc)));

  return pathpairarray;
}


void
Stage1hr_paired_setup (Mode_T mode_in, int index1part_in, int index1interval_in, int index1part_tr_in,
		       Transcriptome_T transcriptome_in, bool genome_align_p_in, bool transcriptome_align_p_in,
		       double user_nmismatches_filter_float_in, double user_mincoverage_filter_float_in,
		       double max_middle_insertions_float_in, double max_middle_deletions_float_in,
		       Chrpos_T shortsplicedist_in, Chrpos_T shortsplicedist_novelend_in,
		       bool splicingp_in, int maxpaths_search_in, int maxpaths_report_in,
		       bool *circularp_in, int pairmax_linear_in, int pairmax_circular_in) {

  mode = mode_in;
  index1part = index1part_in;
  index1interval = index1interval_in;
  index1part_tr = index1part_tr_in;

  transcriptome = transcriptome_in;
  genome_align_p = genome_align_p_in;
  transcriptome_align_p = transcriptome_align_p_in;
  user_nmismatches_filter_float = user_nmismatches_filter_float_in;
  user_mincoverage_filter_float = user_mincoverage_filter_float_in;

  max_middle_insertions_float = max_middle_insertions_float_in;
  max_middle_deletions_float = max_middle_deletions_float_in;

  shortsplicedist = shortsplicedist_in;
  shortsplicedist_novelend = shortsplicedist_novelend_in;

  splicingp = splicingp_in;
  maxpaths_search = maxpaths_search_in;
  maxpaths_report = maxpaths_report_in;

  circularp = circularp_in;
  pairmax_linear = pairmax_linear_in;
  pairmax_circular = pairmax_circular_in;

  return;
}
