/*
 * puzzle.h
 *
 *
 * Part of TREE-PUZZLE 5.2 (February 2005)
 *
 * (c) 2003-2005 by Heiko A. Schmidt, Korbinian Strimmer, and Arndt von Haeseler
 * (c) 1999-2003 by Heiko A. Schmidt, Korbinian Strimmer,
 *                  M. Vingron, and Arndt von Haeseler
 * (c) 1995-1999 by Korbinian Strimmer and Arndt von Haeseler
 *
 * All parts of the source except where indicated are distributed under
 * the GNU public licence.  See http://www.opensource.org for details.
 *
 * ($Id$)
 *
 */


#ifndef _PUZZLE_
#define _PUZZLE_

#ifndef PACKAGE
#  define PACKAGE    "tree-puzzle"
#endif
#ifndef VERSION
#  define VERSION    "5.2-generic"
#endif
#define DATE       "February 2005"

/* shall we use RecDetec, or VisRec format to output informative sites */
#define USE_RECDETEC FALSE

/* prototypes */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#include "pstep.h"
#include "util.h"
#include "ml.h"
#include "consensus.h"
#include "treesort.h"
#ifdef PARALLEL
#  include "ppuzzle.h"
#endif


#define STDOUT stdout

/* time check interval in seconds for ML/puzzling step status (900 = 15min) */
#  define TIMECHECK_INTERVAL 900

/* filenames */
#  define FILENAMELENGTH 2048

/* maximum exp difference, such that 1.0+exp(-TP_MAX_EXP_DIFF) == 1.0 */
#  define TP_MAX_EXP_DIFF 40

#  define INFILEDEFAULT      "infile"
#  define OUTFILEDEFAULT     "outfile"
#  define TREEFILEDEFAULT    "outtree"
#  define INTREEDEFAULT      "intree"
#  define DISTANCESDEFAULT   "outdist"
#  define TSTVDEFAULT        "outtstv"
#  define EDITDISTDEFAULT    "outeditdist"
#  define SITEFREQSDEFAULT   "outsitefreqs"
#  define TRIANGLEEPSDEFAULT "outlm.eps"
#  define TRIANGLESVGDEFAULT "outlm.svg"
#  define UNRESOLVEDDEFAULT  "outqlist"
#  define LMAPTABDEFAULT     "outlmaptab"
#  define ALLQUARTDEFAULT    "outallquart"
#  define ALLQUARTLHDEFAULT  "outallquartlh"
#  define SITELHDEFAULT      "outsitelh"
#  define SITELHBDEFAULT     "outsitelhb"
#  define SITERATEDEFAULT    "outsiterate"
#  define SITERATEBDEFAULT   "outsiterateb"
#  define OUTPARAMDEFAULT    "outparam"
#  define SUBSETDEFAULT      "insubsetmatr"
#  define OUTPTLISTDEFAULT   "outpstep"
#  define OUTPTORDERDEFAULT  "outptorder"
#  define OUTPTALLDEFAULT    "outptall"
#  define NEXALLDEFAULT      "outall.nex"
#  define NEXPTORDERDEFAULT  "outptorder.nex"
#  define NEXPTSPLITSDEFAULT "outptsplits.nex"
#  define PTSPLITSDEFAULT    "outptsplits"
#  define PTSPLITSDEFAULT    "outptsplits"
#  define RDSTATSDEFAULT     "outrdstats"
#  define ALIINFODEFAULT     "outaliinfo"
#  define ALIINFONUMDEFAULT  "outaliinfonum"
#  define SPLITOCCURDEFAULT  "outsplitoccur"

#  define INFILE      infilename
#  define OUTFILE     outfilename
#  define TREEFILE    outtreename
#  define INTREE      intreename
#  define DISTANCES   outdistname
#  define TSTV        outtstvname
#  define EDITDIST    outeditdistname
#  define SITEFREQS   outsitefreqsname
#  define TRIANGLEEPS outlmepsname
#  define TRIANGLESVG outlmsvgname
#  define UNRESOLVED  outqlistname
#  define LMAPTAB     outlmaptabname
#  define ALLQUART    outallquartname
#  define ALLQUARTLH  outallquartlhname
#  define SITELH      outsitelhname
#  define SITELHB     outsitelhbname
#  define SITERATE    outsiteratename
#  define SITERATEB   outsiteratebname
#  define OUTPARAM    outparamname
#  define SUBSET      insubsetmatrname
#  define OUTPTLIST   outpstepname
#  define OUTPTORDER  outptordername
#  define OUTPTALL    outptallname
#  define NEXALL      nexallname
#  define NEXPTORDER  nexptordername
#  define NEXPTSPLITS nexptsplitsname
#  define PTSPLITS    ptsplitsfilename
#  define RDSTATS     rdstatsfilename
#  define ALIINFO     aliinfofilename
#  define ALIINFONUM  aliinfonumfilename
#  define SPLITOCCUR  splitoccurfilename

#  define FILEPREFIX  fileprefixname
#  define PARAMFILE   paramfilename
      

EXTERN char infilename         [FILENAMELENGTH];
EXTERN char outfilename        [FILENAMELENGTH];
EXTERN char outtreename        [FILENAMELENGTH];
EXTERN char intreename         [FILENAMELENGTH];
EXTERN char outdistname        [FILENAMELENGTH];
EXTERN char outtstvname        [FILENAMELENGTH];
EXTERN char outeditdistname    [FILENAMELENGTH];
EXTERN char outsitefreqsname   [FILENAMELENGTH];
EXTERN char outlmepsname       [FILENAMELENGTH];
EXTERN char outlmsvgname       [FILENAMELENGTH];
EXTERN char outqlistname       [FILENAMELENGTH];
EXTERN char outlmaptabname     [FILENAMELENGTH];
EXTERN char outallquartname    [FILENAMELENGTH];
EXTERN char outallquartlhname  [FILENAMELENGTH];
EXTERN char outsitelhname      [FILENAMELENGTH];
EXTERN char outsitelhbname     [FILENAMELENGTH];
EXTERN char outsiteratename    [FILENAMELENGTH];
EXTERN char outsiteratebname   [FILENAMELENGTH];
EXTERN char outparamname       [FILENAMELENGTH];
EXTERN char insubsetmatrname   [FILENAMELENGTH];
EXTERN char outpstepname       [FILENAMELENGTH];
EXTERN char outptordername     [FILENAMELENGTH];
EXTERN char outptallname       [FILENAMELENGTH];
EXTERN char nexallname         [FILENAMELENGTH];
EXTERN char nexptordername     [FILENAMELENGTH];
EXTERN char nexptsplitsname    [FILENAMELENGTH];
EXTERN char ptsplitsfilename   [FILENAMELENGTH];
EXTERN char rdstatsfilename    [FILENAMELENGTH];
EXTERN char splitoccurfilename [FILENAMELENGTH];
EXTERN char aliinfofilename    [FILENAMELENGTH];
EXTERN char aliinfonumfilename [FILENAMELENGTH];

EXTERN char fileprefixname     [FILENAMELENGTH];
EXTERN char paramfilename      [FILENAMELENGTH];
EXTERN FILE *stdinput_fp;

#define OUTFILEEXT     "puzzle"
#define TREEFILEEXT    "tree"
#define DISTANCESEXT   "dist"
#define TSTVEXT        "tstv"
#define EDITDISTEXT    "editdist"
#define SITEFREQSEXT   "sitefreqs"
#define TRIANGLEEPSEXT "eps"
#define TRIANGLESVGEXT "svg"
#define UNRESOLVEDEXT  "qlist"
#define LMAPTABEXT     "lmaptab"
#define ALLQUARTEXT    "allquart"
#define ALLQUARTLHEXT  "allquartlh"
#define SITELHEXT      "sitelh"
#define SITELHBEXT     "sitelhb"
#define SITERATEEXT    "siterate"
#define SITERATEBEXT   "siterateb"
#define OUTPARAMEXT    "param"
#define SUBSETEXT      "subsetmatr"
#define OUTPTLISTEXT   "pstep"
#define OUTPTORDEREXT  "ptorder"
#define OUTPTALLEXT    "ptall"
#define NEXALLEXT      "nex"
#define NEXPTORDEREXT  "ptorder.nex"
#define NEXPTSPLITSEXT "ptsplits.nex"
#define PTSPLITSEXT    "splits"
#define RDSTATSEXT     "rdstats"
#define ALIINFOEXT     "aliinfo"
#define ALIINFONUMEXT  "aliinfonum"
#define SPLITOCCUREXT  "splitoccur"


/* resetprefix values  (xxx) */
#define QUARTET_MISSING 0
#define QUARTET_UNRES   1
#define QUARTET_PARTLY  2
#define QUARTET_FULLY   3

/* resetprefix values  (xxx) */
#define RESET_NONE   0
#define RESET_INFILE 1
#define RESET_INTREE 2

/* setprefix_optn values  (xxx) */
#define SETPREFIX_NONE   0
#define SETPREFIX_INFILE 1
#define SETPREFIX_INTREE 2
#define SETPREFIX_RESET  3
#define SETPREFIX_PREFIX 4

/* setparamfile_optn values  (xxx) */
#define SETPARAMFILE_NONE   0
#define SETPARAMFILE_TRUE   1

/* auto_aamodel/auto_datatype values  (xxx) */
#define AUTO_OFF      0
#define AUTO_GUESS    1
#define AUTO_DEFAULT  2


/* qptlist values  (xxx) */
#define PSTOUT_NONE      0
#define PSTOUT_ORDER     1
#define PSTOUT_LISTORDER 2
#define PSTOUT_LIST      3

/* saveptall_optn values  (xxx) */
#define PTALL_NONE      0
#define PTALL_OUT       1

/* savelmaptab_optn values  (xxx) */
#define LMAPTAB_NONE      0
#define LMAPTAB_OUT       1

/* dtat_optn values  (xxx) */
#define NUCLEOTIDE 0
#define AMINOACID  1
#define BINARY     2

/* typ_optn values  (xxx) */
#define TREERECON_OPTN 0
#define LIKMAPING_OPTN 1
#define NUMTYPES 2

/* puzzlemodes (xxx) */
#define QUARTPUZ 0
#define USERTREE 1
#define CONSENSUS 2
#define PAIRDIST 3
#define NUMPUZZLEMODES 4

/* modes for rootsearch (xxx) */
#define ROOT_USER 0
#define ROOT_AUTO 1
#define ROOT_DISPLAYED 2
#define NUMROOTSEARCH 3

#if 0
/* rhetmodes (xxx) Modes of rate heterogeneity */
#define UNIFORMRATE 0
#define GAMMARATE   1
#define TWORATE     2
#define MIXEDRATE   3
#endif

/* defines for types of quartet likelihood computation (approxqp_optn) */
#define QUART_EXACT  0
#define QUART_APPROX 1

/* defines for types of quartet evaluation (quartcrit_optn) */
#define QUART_MLAPPROX 0
#define QUART_MLEXACT  1
#define QUART_MP       2
#define QUART_ME       3
#define QUART_NJ       4

#ifdef QUART_TEST
#	define QUART_MAX QUART_NJ + 1
#else
#	define QUART_MAX QUART_MLEXACT + 1
#endif

/* defines for results of sequence number check (seqnumcheck) */
#define SEQNUM_OK 0
#define SEQNUM_TOOFEW 1
#define SEQNUM_TOOMANY 2


#if 0
	typedef struct {
		uli fullres_pro;
		uli fullres_con;
		uli partres_pro;
		uli partres_con;
		uli unres;
		uli missing;
		uli qsum;
	} qsupportarr_t;
	
	EXTERN cmatrix biparts;      /* bipartitions of tree of current puzzling step */
	EXTERN cmatrix consbiparts;  /* bipartitions of majority rule consensus tree */
	
	EXTERN int xsize;            /* depth of consensus tree picture */
	EXTERN ivector consconfid;   /* confidence values of majority rule consensus tree */
	EXTERN ivector conssizes;    /* partition sizes of majority rule consensus tree */
	EXTERN ivector xcor;         /* x-coordinates of consensus tree nodes */
	EXTERN ivector ycor;         /* y-coordinates of consensus tree nodes */
	EXTERN ivector ycormax;      /* maximal y-coordinates of consensus tree nodes */
	EXTERN ivector ycormin;      /* minimal y-coordinates of consensus tree nodes */
	
	/* splits for consensus */
	EXTERN int splitlength;      /* length of one entry in splitpatterns */
	EXTERN uli maxbiparts;       /* memory reserved for maxbiparts bipartitions */
	EXTERN uli numbiparts;       /* number of different bipartitions */
	
	EXTERN int *splitsizes;      /* size of all different splits of all trees */
	EXTERN uli *splitcomptemp;   /* temp variable to compress bipartitions coding */
	EXTERN uli *splitfreqs;      /* frequencies of different splits of all trees */
	EXTERN uli *splitpatterns;   /* all different splits of all trees */
	
	EXTERN qsupportarr_t *qsupportarr; /* quartet support values per split */
	
	EXTERN uli consincluded;     /* number of included biparts in the consensus tree */
	EXTERN uli consfifty;        /* number of biparts >= 50% */
	EXTERN uli conscongruent;    /* number of first incongruent bipart */
#endif

/* variables */
EXTERN cmatrix Seqchars;     /* characters contained in data set */
EXTERN ivector Seqgapchar;   /* counter for gaps contained in sequence */
EXTERN ivector Seqotherchar; /* counter for ambiguous contained in sequence */
EXTERN cmatrix treepict;     /* picture of consensus tree */
EXTERN double minscore;      /* value of edgescore on minedge */
EXTERN double tstvf84;       /* F84 transition/transversion ratio */
EXTERN double tstvratio;     /* expected transition/transversion ratio */
EXTERN double yrtsratio;     /* expected pyrimidine/purine transition ratio */
EXTERN dvector ulkl;         /* log L of user trees */
EXTERN dmatrix allsites;     /* log L per sites of utrees (numutrees,Numptrn) */
EXTERN dvector ulklc;        /* log L of utrees (clock) (numutrees,Numptrn) */
EXTERN dmatrix allsitesc;    /* log L per sites of user trees (clock) */
EXTERN FILE *utfp;           /* pointer to user tree file */
EXTERN FILE *ofp;            /* pointer to output file */
EXTERN FILE *seqfp;          /* pointer to sequence input file */
EXTERN FILE *tfp;            /* pointer to tree file */
EXTERN FILE *dfp;            /* pointer to distance file */
EXTERN FILE *tstvfp;         /* pointer to tstv file */
EXTERN FILE *editdistfp;     /* pointer to editdist file */
EXTERN FILE *sitefreqsfp;    /* pointer to sitefreqs file */
EXTERN FILE *triepsfp;       /* pointer to triangle EPS file */
EXTERN FILE *trisvgfp;       /* pointer to triangle SVG file */
EXTERN FILE *lmaptabfp;      /* pointer to file with likelihood mapping table */
EXTERN FILE *unresfp;        /* pointer to file with unresolved quartets */
EXTERN FILE *rdsfp;          /* pointer to file with RecDetec stats */
EXTERN FILE *aliinfofp;      /* pointer to file with alignment information */
EXTERN FILE *aliinfonumfp;   /* pointer to file with alignment information (counts) */
EXTERN FILE *splitoccurfp;   /* pointer to file with split vs tree occurrence information */
EXTERN FILE *tmpfp;          /* pointer to temporary file */
EXTERN FILE *qptlist;        /* pointer to file with puzzling step trees */
EXTERN FILE *qptorder;       /* pointer to file with unique puzzling step trees */
EXTERN int SHcodon;          /* whether SH should be applied to 1st, 2nd codon positions */
EXTERN int utree_optn;       /* use first user tree for estimation */
EXTERN int listqptrees_optn; /* list puzzling step trees */
EXTERN int approxqp_optn;    /* approximate QP quartets */
EXTERN int quartcrit_optn;   /* evaluation criterion for QP quartets (ML, MP, ME, NJ) */
EXTERN int lmapcol_optn;     /* coloring scheme for likelihood mapping, TODO: move to lmap.h */
EXTERN int lmapeps_optn;     /* plot likelihood mapping in EPS format, TODO: move to lmap.h */
EXTERN int lmapsvg_optn;     /* plot likelihood mapping in SVG format, TODO: move to lmap.h */
EXTERN int paramfile_optn;   /* read parameters from file rather than stdin */
EXTERN int rootstart_optn;   /* always start from a quartet containing the outgroup */
EXTERN int rootquartsonly_optn; /* use only quartets containing the outgroup */

EXTERN int codon_optn;       /* declares what positions in a codon should be used */
EXTERN int compclock;        /* computation of clocklike branch lengths */
EXTERN int chooseA;          /* leaf variable */
EXTERN int chooseB;          /* leaf variable */
EXTERN int clustA, clustB, clustC, clustD; /* number of members of LM clusters */

EXTERN int Frequ_optn;       /* use empirical base frequencies */

/* PSTEP_ORIG_H */
EXTERN int Maxbrnch;         /* 2*Maxspc - 3 */

EXTERN int Maxseqc;          /* number of sequence characters per taxum */
EXTERN int mflag;            /* flag used for correct printing of runtime messages */

EXTERN int numclust;         /* number of clusters in LM analysis */
EXTERN int outgroup;         /* outgroup */
EXTERN int puzzlemode;       /* computation of QP tree and/or ML distances */
EXTERN int rootsearch;       /* how location of root is found */
EXTERN int rhetmode;         /* model of rate heterogeneity */
EXTERN int seqnumcheck;      /* result of sequence number checkheterogeneity  */
EXTERN int usebestq_optn;    /* use only best quartet topology, no bayesian weights */
EXTERN int printrmatr_optn;  /* print rate matrix to screen */
EXTERN int usebranch_optn;   /* use branch lengths given in usertree */
EXTERN int show_optn;        /* show unresolved quartets    */
EXTERN int exit_wait_optn;   /* wait for return on exit */
EXTERN int savelmaptab_optn; /* save likelihood mapping table to file */
EXTERN int savequart_optn;   /* save memory block which quartets to file */
EXTERN int savequartlh_optn; /* save quartet likelihoods to file */
EXTERN int saveqlhbin_optn;  /* save quartet likelihoods binary */
EXTERN int saveqlhblen_optn; /* save inner branch lenghs */
EXTERN int savesitelh_optn;  /* save site likelihoods (PHILIP-like) */
EXTERN int savesitelhb_optn; /* save site likelihoods (binary) */
EXTERN int savesiterate_optn;       /* save site rates (PHILIP-like) */
EXTERN int savesiterateb_optn;      /* save site rates (binary) */
EXTERN int savetstv_optn;           /* write pairwise substitutions counts to PREFIX.tstv */
EXTERN int saveeditdist_optn;       /* write pairwise substitutions counts to PREFIX.editdist */
EXTERN int savesitefreqs_optn;      /* write site frequencies to PREFIX.sitefreqs */
EXTERN int saverdstatsfile_optn;    /* save stats for RecDetec to stats file */
EXTERN int savealiinfofile_optn;    /* save parsimony information content along ali to file */
EXTERN int savealiinfonumfile_optn; /* save parsimony information content (counts) along ali to file */
EXTERN int stopafteralistats_optn;  /* stop after saving alignment stats */
EXTERN int savesplitoccurfile_optn; /* save split occurrences to file */
EXTERN int saveptsplitsfile_optn;   /* save splits to splits file */
EXTERN int savenexus_optn;          /* save nexus file */
EXTERN int savenexusjoin_optn;      /* save joint nexus file */
EXTERN int savenexusptsplits_optn;  /* save puzzling tree as splits to nexus file */
EXTERN int savenexusptorder_optn;   /* save puzzling trees to nexus file */
EXTERN int readquart_optn;          /* read memory block which quartets from file */
EXTERN int fixedorder_optn;         /* use fixed puzzling insert order 1,2,3,...n */
#if 0
EXTERN int skipmlbranch_optn;/* skip ml branches in final tree */ 
#endif
EXTERN int conssub50_optn;   /* do  consensus down to percentage of first incongruence/ambiguity */
EXTERN int qsupport_optn;    /* compute quartet support for the splits */
EXTERN int dotreetest_optn;  /* compute tree statistics (ELW, KH, SH) */
EXTERN int dotreelh_optn;    /* compute lh/branch lengths (QP,consensus) */
EXTERN int setprefix_optn;   /* use other FILEPREFIX that INFILENAME */
EXTERN int saveptall_optn;   /* successive output of every puzzling step tree */
EXTERN int consensus_optn;   /* do consensus tree instead of user trees */
EXTERN int sym_optn;         /* symmetrize doublet frequencies */
EXTERN int ytaxcounter;      /* counter for establishing y-coordinates of all taxa */
EXTERN int numutrees;        /* number of users trees in input tree file */
EXTERN ivector clusterA, clusterB, clusterC, clusterD;  /* clusters for LM analysis */

EXTERN ivector ycortax;      /* y-coordinates of all taxa */

EXTERN uli badqs;            /* number of bad quartets */
EXTERN uli unresqs;          /* number of unresolved quartets, formerly badqs */
EXTERN uli partresqs;        /* number of partly resolved quartets */
EXTERN uli fullresqs;        /* number of fully resolved quartets */
EXTERN uli missingqs;        /* number of fully resolved quartets */
EXTERN ulivector badtaxon;   /* involment of each taxon in a bad quartet */
EXTERN ulimatrix qinfomatr;  /* sums of quartet topologies per taxon [0]=sum */
EXTERN uli Currtrial;        /* counter for puzzling steps */

EXTERN uli Numquartets;      /* number of quartets */
EXTERN uli Numtrial;         /* number of puzzling steps */
EXTERN uli lmqts;            /* quartets investigated in LM analysis (0 = ALL) */


EXTERN uli aliinfo_ws;             /* window size for informative sites along ali */
EXTERN uli aliinfo_ss;             /* window step size for informative sites along ali */
EXTERN uli inform;                 /* informative sites */
EXTERN uli fullinform;             /* fully informative sites */
EXTERN uli partinform;             /* partly informative sites */
EXTERN uli noninform;              /* non-informative sites */
EXTERN uli varnoninform;           /* variable, but non-informative sites */
EXTERN uli constantgaps;           /* constant sites+gaps */
EXTERN uli constant;               /* constant sites */
EXTERN ivector siteinform;         /* type of informative site */
EXTERN ulivector gapvec;           /* gap/wildcard counts at site */
EXTERN ulivector taxinform;        /* informative sites per taxon */
EXTERN ulivector taxnoninform;     /* non-informative sites per taxon */

EXTERN int auto_datatype;       /* guess datatype ? */
EXTERN int guessdata_optn;      /* guessed datatype */

EXTERN int auto_aamodel;        /* guess amino acid modell ? */
EXTERN int guessauto_aamodel;   /* guessed amino acid modell ? */
EXTERN int guessDayhf_optn;     /* guessed Dayhoff model option */
EXTERN int guessJtt_optn;       /* guessed JTT model option */
EXTERN int guessblosum62_optn;  /* guessed BLOSUM 62 model option */
EXTERN int guessmtrev_optn;     /* guessed mtREV model option */
EXTERN int guesscprev_optn;     /* guessed cpREV model option */
EXTERN int guessvtmv_optn;      /* guessed VT model option */
EXTERN int guesswag_optn;       /* guessed WAG model option */
EXTERN int guesslg_optn;        /* guessed LG model option */
/* EXTERN int guesspoisson_optn; */  /* guessed Poisson model (JC for proteins) option */
/* EXTERN int guessequalin_optn; */  /* guessed Equalin model option */
/* EXTERN int guessmtmam_optn;   */  /* guessed mtMAM model option */
/* EXTERN int guessrtrev_optn;   */  /* guessed rtREV model option */


/* definitions for information along the alignment */
#define UNKNOWN     0
/* informative sites are FULLINFO + PARTINFO */
#define FULLINFO    1
#define PARTINFO    2
/* all non-informative sites are VARNONINFO + CONSTSITE + COSTSGAPS */
#define VARNONINFO  3
#define CONSTSITE   4
#define CONSTGAPS   5
#define GAPS        6

/* missing data: for handling subsets */
EXTERN int     readsubset_optn;           /* read subset option */
EXTERN int     Maxsubset;                 /* number of subsets */
EXTERN imatrix ss_setovlgraph;            /* size of overlap >= 3 between 2 subsets */
EXTERN imatrix ss_setoverlaps;            /* size of overlap between 2 subsets */
EXTERN imatrix ss_setovllist;             /* list with ovlerlapping subsets */
EXTERN ivector ss_setovllistsize;         /* size of list with ovlerlapping subsets */
EXTERN imatrix ss_matrix;                 /* boolean list: taxon in set? */
EXTERN imatrix ss_list;                   /* list of taxa in set */
EXTERN ivector ss_listsize;                /* size of list with taxa */

#if 0
/* counter variables needed in likelihood mapping analysis */
EXTERN uli ar1, ar2, ar3;
EXTERN uli reg1, reg2, reg3, reg4, reg5, reg6, reg7;
EXTERN uli reg1l, reg1r, reg2u, reg2d, reg3u, reg3d,
 reg4u, reg4d, reg5l, reg5r, reg6u, reg6d;
#endif

/* single counter array needed in likelihood mapping analysis */
/* (makes above counters obsolete - up/down,right/left never needed) (HAS) */
#define LM_REG1 0
#define LM_REG2 1
#define LM_REG3 2
#define LM_REG4 3
#define LM_REG5 4
#define LM_REG6 5
#define LM_REG7 6
#define LM_AR1  7
#define LM_AR2  8
#define LM_AR3  9
#define LM_MAX  10
EXTERN uli **qcountarray;

EXTERN unsigned char *quartetinfo; /* place where quartets are stored */
EXTERN dvector qweight; /* for use in QP and LM analysis */
EXTERN dvector sqdiff;
EXTERN ivector qworder;
EXTERN ivector sqorder;

EXTERN int randseed;
EXTERN int psteptreestrlen;

#if 0
	typedef struct treelistitemtypedummy {
		struct treelistitemtypedummy *pred;
		struct treelistitemtypedummy *succ;
		struct treelistitemtypedummy *sortnext;
		struct treelistitemtypedummy *sortlast;
		char  *tree;
		int    count;
		int    id;
		int    idx;
	} treelistitemtype;
	
	EXTERN treelistitemtype *psteptreelist;
	EXTERN treelistitemtype *psteptreesortlist;
	EXTERN int               psteptreenum;
	EXTERN int               psteptreesum;
#endif


/* prototypes */
void tp_exit(int exitcode, char *exitstr, int printline, char *fname, int fline, int dowait);
void makeF84model(void);
void compnumqts(void);
void setoptions(FILE *);
int  openfiletoread(FILE **, char[], char[], FILE *);
int  openfiletowrite(FILE **, char[], char[], FILE *);
int  openfiletoappend(FILE **, char[], char[], FILE *);
void closefile(FILE *);
void symdoublets(void);
void computeexpectations(void);
void putdistance(FILE *);
void puttstv();
void puteditdist();
#if 0
void count_tstv(ulimatrix *ts, ulimatrix *tv);
void count_editdist(ulimatrix *ts, ulimatrix *tv);
#endif
void findidenticals(FILE *);
double averagedist(int maxspc, dmatrix  distanmat, double *meandist, double *mindist, double *maxdist, double *stddevdist, double *vardist);

/***  Likelihood mapping routines (TODO: move to lmap.c/h)  ***/
/***  lmapcol_optn, initeps, finisheps, initsvg, finishsvg, makelmpoint, plotlmpointcolor, plotlmpoint  ***/
/* lmapcol_optn values (xxx) */
#define LMAP_NORMAL    0
#define LMAP_AREA      1
#define LMAP_MINMAXLEN 2
   /* first lines of EPSF likelihood mapping file */
   void initeps(FILE *ofp);
   /* last lines of EPSF likelihood mapping file */
   void finisheps(FILE *ofp, uli **countarr);

   /* first lines of SVG likelihood mapping file */
   void initsvg(FILE *ofp);
   /* last lines of SVG likelihood mapping file */
   void finishsvg(FILE *ofp, uli **countarr);

   /* computes LM point from the three log-likelihood values,
      plots the point, and does some statistics */
   /* input: log-likelihoods=b1/b2/b3, internal quartet edge length=bl1/bl2/bl3 */
   /*        min edgelen=minlen, max edgelen=maxlen, how to color=coltype */
   /* void makelmpoint(FILE *fp, double b1, double b2, double b3, double bl1, double bl2, double bl3, double minlen, double maxlen, int coltype); */
   void makelmpoint(
	FILE   *fpeps, 				/* output file pointer (EPS) */
	FILE   *fpsvg, 				/* output file pointer (SVG) */
	double  b1, 				/* log-likelihood: ab|cd */
	double  b2, 				/* log-likelihood: ac|bd */
	double  b3, 				/* log-likelihood: ad|bc */
#if 0
	uli *reg1, uli *reg2, uli *reg3, 	/* simplex reagions for counting */
	uli *reg4, uli *reg5, uli *reg6, 
	uli *reg7, 
	uli *ar1, uli *ar2, uli *ar3, 
	uli *reg1l, uli *reg1r, 
	uli *reg2u, uli *reg2d, 
	uli *reg3u, uli *reg3d, 
	uli *reg4u, uli *reg4d, 
	uli *reg5l, uli *reg5r, 
	uli *reg6u, uli *reg6d,
	int *ar, int *reg, 
#endif
	int t1, int t2, int t3, int t4,		/* four taxa in the quartet */
	uli **countarr,				/* taxon-specific  */
	double  bl1, 				/* internal branchlength: ab|cd */
	double  bl2, 				/* internal branchlength: ac|bd */
	double  bl3, 				/* internal branchlength: ad|bc */
	double  minlen, 			/* lower branch-length bound */
	double  maxlen, 			/* upper branch-length bound */
	int     coltype				/* color to plot points on the branch-length bound */
	);

   /* plot one point of likelihood mapping analysis */
   void plotlmpointcolor(FILE *epsofp, FILE *svgofp, double w1, double w2, int red, int green, int blue);
   /* void plotlmpointcolor(FILE *ofp, double w1, double w2, int red, int green, int blue); */
   /* plot one point of likelihood mapping analysis */
   /* void plotlmpoint(FILE *ofp, double w1, double w2); */
   void plotlmpoint(FILE *epsofp, FILE *svgofp, double w1, double w2);

void timestamp(FILE *);

/* write output file */
void writeoutputfile(FILE *ofp, int part, int clockmode);

/* definitions for writing output */
#define WRITEALL    0
#define WRITEPARAMS 1
#define WRITEREST   2

void writetimesstat(FILE *ofp);
/* write current user tree to file */
void writecutree(FILE *ofp, int num, int clockmode);

void starttimer(void);
void checktimer(uli);

/* void estimateparametersnotree(void); * moved to mlparam.c */
/* void estimateparameterstree(void);   * moved to mlparam.c */

int main(int, char *[]);
int ulicmp(const void *, const void *);
int intcmp(const void *, const void *);

void readid(FILE *infp,        /* in:  file pointer to read from */
            int t,             /* in:  current taxon number */
            cmatrix  identif);  /* io:  taxon names (10 char w/o stop) */

char readnextcharacter(FILE *, int, int);

/* skip rest of the line */
void skiprestofline(FILE *ifp,    /* input file stream */
                    int   notu,   /* taxon number      - for error msg. */
                    int   nsite); /* sequence position - for error msg. */

/* skip control characters and blanks */
void skipcntrl(FILE *ifp,    /* input file stream */
               int   notu,   /* taxon number      - for error msg. */
               int   nsite); /* sequence position - for error msg. */

/* read sequences of one data set */
void getseqs(FILE    *ifp,      /* in:  input file stream */
             int      Maxspc,   /* in:  number of taxa */
             int      Maxseqc,  /* in:  number of sites */
             cmatrix *seqch,    /* out: alignment matrix */
             cmatrix  identif); /* io:  taxon names (10 char w/o stop) */

/* initialize identifer arrays */
void initid(int      t,        /* in:  number of taxa */
            cmatrix *identif,  /* out: name array w/o end of string */
            cmatrix *namestr); /* out: name array with end of string */

/* copy undelimited identifer array to '\0' delimited identifer array */
void identif2namestr(int     num,      /* number of taxa         */
                     cmatrix Identif,  /* non-delimited names    */
                     cmatrix Namestr); /* proper delimited names */

void fputid10(FILE *, int);
int fputid(FILE *, int);

/* read first line of sequence data set */
void getsizesites(FILE *ifp,      /* in: input file stream */
                  int  *Maxspc,   /* out: number of taxa */
                  int  *Maxseqc); /* out: number of sites */

/* read alignment from file */
void readsequencefile(FILE    *seqfp,     /* in:  sequence input file stream */
                      int     *Maxspc,    /* out: number of taxa             */
                      int     *Maxseqc,   /* out: number of sites            */
                      cmatrix *identif,   /* out: name array w/o end of str  */
                      cmatrix *namestr,   /* out: name array with end of str */
                      cmatrix *Seqchars); /* out: alignment matrix           */

/* read subsets from file */
void readsubsetfile(FILE    *seqfp,              /* in:  sequence input file stream */
                    int      Maxspc,             /* in:  number of taxa             */
                    cmatrix  namestr,            /* in:  names taxa (seq file)      */
                    int     *Maxsubset,          /* out: number of subsets          */
                    imatrix *ss_setovlgraph,     /* out: size of overlap >= 3 between 2 subsets */
                    imatrix *ss_setoverlaps,     /* out: size of overlap between 2 subsets */
                    imatrix *ss_setovllist,      /* out: list with ovlerlapping subsets */
                    ivector *ss_setovllistsize,  /* out: size of list with ovlerlapping subsets */
                    imatrix *ss_matrix,          /* out: boolean list: taxon in set? */
                    imatrix *ss_list,            /* out: list of taxa in set */
                    ivector *ss_listsize);        /* out: size of list with taxa */

/* permute taxon order */
void permutetaxa_ss(int      Maxspc,        /* in:  number of taxa           */
                    ivector  permutation,   /* permuted taxon order          */
                    cmatrix  namestr,       /* in:  names taxa (seq file)    */
                    int      Maxsubset,     /* out: number of subsets        */
                    imatrix  ss_setovlgraph,/* out: size of overlap >= 3 between 2 subsets */
                    imatrix  ss_setoverlaps,/* out: size of overlap between 2 subsets */
                    imatrix  ss_setovllist, /* out: list with overlapping subsets */
                    ivector  ss_setovllistsize,/* out: size of list with ovlerlapping subsets */
                    imatrix  ss_matrix,     /* out: bool list: taxon in set? */
                    imatrix  ss_list,       /* out: list of taxa in set */
                    ivector  ss_listsize);  /* out: size of list with taxa */

/* print subsets */
void fprintfss(FILE    *ofp,              /* in:  output file stream         */
             int      Maxspc,             /* in:  number of taxa             */
             int      Maxsubset,          /* out: number of subsets          */
             imatrix  ss_setovlgraph,     /* out: size of overlap >= 3 between 2 subsets */
             imatrix  ss_setoverlaps,     /* out: size of overlap between 2 subsets */
             imatrix  ss_setovllist,      /* out: list with ovlerlapping subsets */
             ivector  ss_setovllistsize,  /* out: size of list with ovlerlapping subsets */
             imatrix  ss_matrix,          /* out: boolean list: taxon in set? */
             imatrix  ss_list,            /* out: list of taxa in set */
             ivector  ss_listsize);        /* out: size of list with taxa */

/* check connectedness of subsets */
void checkss(FILE    *ofp,              /* in:  output file stream         */
             int      Maxspc,             /* in:  number of taxa             */
             int      Maxsubset,          /* out: number of subsets          */
             imatrix  ss_setovlgraph,     /* out: size of overlap >= 3 between 2 subsets */
             imatrix  ss_setoverlaps,     /* out: size of overlap between 2 subsets */
             imatrix  ss_setovllist,      /* out: list with ovlerlapping subsets */
             ivector  ss_setovllistsize,  /* out: size of list with ovlerlapping subsets */
             imatrix  ss_matrix,          /* out: boolean list: taxon in set? */
             imatrix  ss_list,            /* out: list of taxa in set */
             ivector  ss_listsize);        /* out: size of list with taxa */

/* guess data type: NUCLEOTIDE:0, AMINOACID:1, BINARY:2 */
int guessdatatype(cmatrix Seqchars,   /* alignment matrix (Maxspc x Maxseqc) */
                  int     Maxspc,     /* number of taxa */
                  int     Maxseqc);   /* number of sites */

void translatedataset(int maxspc, int maxseqc, int *maxsite, cmatrix seqchars, cmatrix *seqchar, ivector *seqgapchar, ivector *seqotherchar);
void estimatebasefreqs(void);
void guessmodel(void);

#if 0
	int *initctree();
	void copytree_trueID(int          *ctree,      /* out: copy for effective sorting */
              	int          *trueID,     /* in:  permutation vector         */
              	ONEEDGE      *edgeset,    /* in: intermediate tree topology  */
              	int          *edgeofleaf, /*     dito.                       */
              	int           nextleaf);  /* in: next free leaf (bound)      */

	void freectree(int **snodes);
	void printctree(int *ctree);
	char *sprintfctree(int *ctree, int strlen);
	void fprintffullpstree(FILE *outf, char *treestr);
	int printfsortctree(int *ctree);
	int sortctree(int *ctree);
	int ct_1stedge(int node);
	int ct_2ndedge(int node);
	int ct_3rdedge(int node);

	void printfpstrees(treelistitemtype *list);
	void printfsortedpstrees(treelistitemtype *list);
	void fprintfsortedpstrees(FILE *output, treelistitemtype *list, int itemnum, int itemsum, int comment, float cutoff);

	void sortbynum(treelistitemtype *list, treelistitemtype **sortlist);
	treelistitemtype *addtree2list(char             **tree,
                               int                numtrees,
                               treelistitemtype **list,
                               int               *numitems,
                               int               *numsum);
	void freetreelist(treelistitemtype **list,
                  	int               *numitems,
                  	int               *numsum);
#endif 

#if 0
	void resetedgeinfo(void);
	void incrementedgeinfo(int, int);
	void minimumedgeinfo(void);
#endif


#if 0
	void initconsensus(void);
	
	/* recursive function to get bipartitions */
	void makepart_trueID(int           i,          /*  */
              	int           curribrnch, /* in: current branch in traversal */
              	ONEEDGE      *edge,       /* in: tree topology    */
              	int          *edgeofleaf, /* in: ext. edge list   */
              	int          *trueID,     /* in: permutation list */
              	cmatrix       biparts,    /* out: split strings, edge by edge */
              	int           Maxspc);	/* in: number of species in tree */
	
	
	/* compute bipartitions of current puzzling step tree */
	void computebiparts_trueID(ONEEDGE      *edge,       /* in: tree topology          */
                    	int          *edgeofleaf, /* in: ext. edge list         */
                    	int          *trueID,     /* in: permutation list       */
                    	cmatrix       biparts,    /* out: splits                */
                    	int           outgroup,   /* in: outgroup of tree       */
                    	int           Maxspc);    /* in: number of taxa in tree */
	
	void printsplit(FILE *, uli);
	
	void makenewsplitentries(cmatrix  bip,             /* in: split string vector */
                         	int      numspl,          /* in: no. of new splits   */
                         	uli    **in_splitpatterns,/* io: known compr splits  */
                         	int    **in_splitsizes,   /* io: kn. split sizes: '.'*/
                         	uli    **in_splitfreqs,   /* io: kn. split frequences*/
                         	uli     *in_numbiparts,   /* io: no. of splits so far*/
	                 	uli     *in_maxbiparts,   /* io: reserved memory     */
                         	int      Maxspc);         /* in: no. of species      */
	
	/* copy bipartition n of all different splitpatterns to consbiparts[k] */
	void copysplit(uli n, uli *splitpatterns, int k, cmatrix consbipartsvec);
	
	void makeconsensus(uli, int);
	
	/* write node (writeconsensustree) */
	void writenode(FILE          *treefile,    /* in: output stream */
               	int            node,        /* current node */
               	int            qsupp_optn,  /* 'print quartet support' flag */
               	qsupportarr_t *qsupparr,    /* quartet support values */
               	int           *column);     /* current line position */
	
	/* write consensus tree */
	void writeconsensustree(FILE          *treefile,   /* in: output stream */
                        	int            qsupp_optn, /* 'print quartsupp' flag */
                        	qsupportarr_t *qsupparr);  /* quartet support values */
	
	void writeconsensustree(FILE *, int, qsupportarr_t *);
	void nodecoordinates(int);
	void drawnode(int, int);
	void plotconsensustree(FILE *);
#endif

unsigned char *callocquartets(int);
void freequartets(void);
unsigned char readquartet(int, int, int, int);
void writequartet(int, int, int, int, unsigned char);
void sort3doubles(dvector, ivector);
void computeallquartets(void);

/* check the branching structure between the leaves (not the taxa!)
   A, B, C, and I (A, B, C, I don't need to be ordered). As a result,
   the two leaves that are closer related to each other than to leaf I
   are found in chooseX and chooseY. If the branching structure is
   not uniquely defined, chooseX and chooseY are chosen randomly
   from the possible taxa */
unsigned char checkquartet(int  A,          /* quartet taxon ID                 */
                  int  B,          /* dito.                            */
                  int  C,          /* dito.                            */
                  int  I,          /* dito., to be inserted            */
                  int *chooseX,    /* (chooseX,chooseY | neighb,I)     */
                  int *chooseY,    /* chooseX+Y are non-neighbors of I */
                  int *neighb,     /* neighb is neighbors of I         */
                  int *status,     /* status of the quartet: 0=missing, 1=unresolved, 2=partly, 3=resolved */
         int       rootquartsonly_optn); /* in: use root quartets only  */


unsigned char checkquartet_trueID(int  A,   /* quartet leaf idx in permutation array */
                  int  B,          /* dito.                                 */
                  int  C,          /* dito.                                 */
                  int  I,          /* dito., to be inserted                 */
                  int *trueID,     /* permutation array                     */
                  int *chooseX,    /* (chooseX,chooseY | neighb,I)          */
                  int *chooseY,    /* chooseX+Y are non-neighbors of I      */
                  int *neighb,     /* neighb is neighbors of I              */
         int       rootquartsonly_optn); /* in: use root quartets only  */

void num2quart(uli qnum, int *a, int *b, int *c, int *d);
uli numquarts(int maxspc);
uli quart2num (int a, int b, int c, int d);

void writetpqfheader(int nspec, FILE *ofp, int flag);


/* extracted from main (xxx) */
/* evaluate ab|cd ac|bd ad|bc, give ML values and inner branch lengths */
void compute_quartlklhds(int a, int b, int c, int d, 
			double *d1, double *d2, double *d3, 
			double *iblen1, double *iblen2, double *iblen3, 
			int approx);


/* definitions for timing */

#define OVERALL   0
#define GENERAL   1
#define OPTIONS   2
#define PARAMEST  3
#define QUARTETS  4
#define PUZZLING  5
#define TREEEVAL  6

typedef struct {
	int      currentjob;
	clock_t  tempcpu;
	clock_t  tempfullcpu;
	clock_t  tempcpustart;
	time_t   temptime;
	time_t   tempfulltime;
	time_t   temptimestart;

        clock_t  maxcpu;
	clock_t  mincpu;
	time_t   maxtime;
	time_t   mintime;

	double   maxcpublock;
	double   mincpublock;
	double   mincputick;
	double   mincputicktime;
	double   maxtimeblock;
	double   mintimeblock;

	double   generalcpu;
	double   optionscpu;
	double   paramestcpu;
	double   quartcpu;
	double   quartblockcpu;
	double   quartmaxcpu;
	double   quartmincpu;
	double   puzzcpu;
	double   puzzblockcpu;
	double   puzzmaxcpu;
	double   puzzmincpu;
	double   treecpu;
	double   treeblockcpu;
	double   treemaxcpu;
	double   treemincpu;
	double   cpu;
	double   fullcpu;

	double   generaltime;
	double   optionstime;
	double   paramesttime;
	double   quarttime;
	double   quartblocktime;
	double   quartmaxtime;
	double   quartmintime;
	double   puzztime;
	double   puzzblocktime;
	double   puzzmaxtime;
	double   puzzmintime;
	double   treetime;
	double   treeblocktime;
	double   treemaxtime;
	double   treemintime;
	double   time;
	double   fulltime;
} timearray_t;

EXTERN double cputime, walltime;
EXTERN double fullcpu, fulltime;
EXTERN double fullcputime, fullwalltime;
EXTERN double altcputime, altwalltime;
EXTERN clock_t cputimestart,  cputimestop, cputimedummy;
EXTERN time_t  walltimestart, walltimestop, walltimedummy;
EXTERN clock_t Startcpu;     /* start cpu time */
EXTERN clock_t Stopcpu;      /* stop cpu time */
EXTERN time_t MLstepStarttime;     /* start time */
EXTERN time_t MLstepStoptime;      /* stop time */
EXTERN time_t PStepStarttime;     /* start time */
EXTERN time_t PStepStoptime;      /* stop time */
EXTERN time_t PEstStarttime;     /* start time */
EXTERN time_t PEstStoptime;      /* stop time */
EXTERN time_t Starttime;     /* start time */
EXTERN time_t Stoptime;      /* stop time */
EXTERN time_t time0;         /* timer variable */
EXTERN time_t time1;         /* yet another timer */
EXTERN time_t time2;         /* yet another timer */
EXTERN timearray_t tarr;

void resetqblocktime(timearray_t *ta);
void resetpblocktime(timearray_t *ta);
void inittimearr(timearray_t *ta);
void addtimes(int jobtype, timearray_t *ta);
#ifdef TIMEDEBUG
  void printtimearr(timearray_t *ta);
#endif /* TIMEDEBUG */

/* compute Bayesian weights from log-lkls d1, d2, d3 */
unsigned char loglkl2weight(int    a,
                            int    b,
                            int    c,
                            int    i,
                            double d1,
                            double d2,
                            double d3,
                            int    usebestq);

#if 0
#ifdef PARALLEL
#  include "ppuzzle.h"
#endif
#endif
#endif /* _PUZZLE_ */

