/*
 * model1.c
 *
 *
 * 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$)
 *
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


/* definitions */
#define EXTERN extern

/* prototypes */
#include <stdio.h>
#include "util.h"
#include "puzzle.h"
#include "ml.h"

/* number of states of the selected model */ 
int gettpmradix()
{
	if (data_optn == 0) { /* nucleotides */
		if (nuc_optn) return 4;
		if (SH_optn) return 16;
	} else if (data_optn == 1) { /* amino acids */
		return 20;
	} else { /* two-state model */
		return 2;
	}
	return 1;
} /* gettpmradix */

/* relative transition frequencies */
void rtfdata(dmatrix q, double *f)
{
	double alp, alpy, alpr;
	int i, j;

	if (data_optn == 0)
	{ /* nucleotides */

		if (nuc_optn)
		{ /* 4x4 nucleotides */
			if (!GTR_optn) {
				alp = 2.0*TSparam;
				alpr = (alp * 2.0) / (YRparam + 1.0);
				alpy = YRparam * alpr;
			
				q[0][1] =1; q[0][2] =alpr; q[0][3] =1;
				q[1][2] =1; q[1][3] =alpy;
				q[2][3] =1;

				GTR_ACrate = q[0][1]; 
				GTR_AGrate = q[0][2]; 
				GTR_ATrate = q[0][3];
				GTR_CGrate = q[1][2]; 
				GTR_CTrate = q[1][3];
				GTR_GTrate = q[2][3];

				f[0] = 0.25; f[1] = 0.25; f[2] = 0.25; f[3] = 0.25;
			} else {
#if 0
				alp = 2.0*TSparam;
				alpr = (alp * 2.0) / (YRparam + 1.0);
				alpy = YRparam * alpr;
#endif
			
				q[0][1] = GTR_ACrate; q[0][2] = GTR_AGrate; q[0][3] = GTR_ATrate;
				q[1][2] = GTR_CGrate; q[1][3] = GTR_CTrate;
				q[2][3] = GTR_GTrate;

				f[0] = 0.25; f[1] = 0.25; f[2] = 0.25; f[3] = 0.25;
			}
		}
		
		if (SH_optn)
		{ /* 16x16 nucleotides */
		
			alp = 2.0*TSparam;
	
			q[0][1]  =1; q[0][2]  =alp; q[0][3]  =1; q[0][4]  =1;
			q[0][5]  =0; q[0][6]  =0;   q[0][7]  =0; q[0][8]  =alp;
			q[0][9]  =0; q[0][10] =0;   q[0][11] =0; q[0][12] =1;
			q[0][13] =0; q[0][14] =0;   q[0][15] =0;
			
			q[1][2]  =1; q[1][3]  =alp; q[1][4]  =0; q[1][5]  =1;
			q[1][6]  =0; q[1][7]  =0;   q[1][8]  =0; q[1][9]  =alp;
			q[1][10] =0; q[1][11] =0;   q[1][12] =0; q[1][13] =1;
			q[1][14] =0; q[1][15] =0;
			
			q[2][3]  =1; q[2][4]  =0;   q[2][5]  =0; q[2][6]  =1;
			q[2][7]  =0; q[2][8]  =0;   q[2][9]  =0; q[2][10] =alp;
			q[2][11] =0; q[2][12] =0;   q[2][13] =0; q[2][14] =1;
			q[2][15] =0;
			
			q[3][4]  =0; q[3][5]  =0;   q[3][6]  =0; q[3][7]  =1;
			q[3][8]  =0; q[3][9]  =0;   q[3][10] =0; q[3][11] =alp;
			q[3][12] =0; q[3][13] =0;   q[3][14] =0; q[3][15] =1;
			
			q[4][5]  =1; q[4][6]  =alp; q[4][7]  =1; q[4][8]  =1;
			q[4][9]  =0; q[4][10] =0;   q[4][11] =0; q[4][12] =alp;
			q[4][13] =0; q[4][14] =0;   q[4][15] =0;
			
			q[5][6]  =1; q[5][7]  =alp; q[5][8]  =0; q[5][9]  =1;
			q[5][10] =0; q[5][11] =0;   q[5][12] =0; q[5][13] =alp;
			q[5][14] =0; q[5][15] =0;
			
			q[6][7]  =1; q[6][8]  =0;   q[6][9]  =0; q[6][10] =1;
			q[6][11] =0; q[6][12] =0;   q[6][13] =0; q[6][14] =alp;
			q[6][15] =0;

			q[7][8]  =0; q[7][9]  =0;   q[7][10] =0; q[7][11] =1;
			q[7][12] =0; q[7][13] =0;   q[7][14] =0; q[7][15] =alp;
			
			q[8][9]  =1; q[8][10] =alp; q[8][11] =1; q[8][12] =1;
			q[8][13] =0; q[8][14] =0;   q[8][15] =0;
			
			q[9][10] =1; q[9][11] =alp; q[9][12] =0; q[9][13] =1;
			q[9][14] =0; q[9][15] =0;
			
			q[10][11]=1; q[10][12]=0;   q[10][13]=0; q[10][14]=1;
			q[10][15]=0;
			
			q[11][12]=0; q[11][13]=0;   q[11][14]=0; q[11][15]=1;
			
			q[12][13]=1; q[12][14]=alp; q[12][15]=1;
			
			q[13][14]=1; q[13][15]=alp;
			
			q[14][15]=1;

			
			for (i = 0; i < 16; i++) f[i] = 0.0625;
		}
	}
	else if (data_optn == 1)
	{ /* amino acids */
		if (Dayhf_optn) /* Dayhoff model */
		{
			dyhfdata(q, f);			
		}
		else if (Jtt_optn) /* JTT model */
		{
			jttdata(q, f);
		}
		else if (blosum62_optn) /* BLOSUM 62 model */
		{
			blosum62data(q, f);
		}
		else if (mtrev_optn) /* mtREV model */
		{
			mtrevdata(q, f);
		} 
		else if (cprev_optn) /* cpREV model */
		{
			cprev45data(q, f);
		} 
		else if (vtmv_optn) /* VT model */
		{
			vtmvdata(q, f);
		}
		else if (wag_optn) /* WAG model */
		{
			wagdata(q, f);
		} 
		else /* if (lg_optn) */ /* LG model */
		{
			lgdata(q, f);
		} 
#if 0
		else if (poisson_optn) /* Poisson model */
		{
			poissondata(q, f);
		} 
		else if (equalin_optn) /* Equalin model */
		{
			equalindata(q, f);
		} 
		else if (mtmam_optn) /* mtMAM model */
		{
			mtmamdata(q, f);
		} 
		else if (rtrev_optn) /* rtREV model */
		{
			rtrevdata(q, f);
		} 
#endif
		
	}
	else /* two-state model */
	{
		q[0][1] = 1.0;
		
		f[0] = 0.5; f[1] = 0.5;
	}
	
	/* fill matrix from upper triangle */
	for (i = 0; i < tpmradix; i++)
	{
		q[i][i] = 0.0;
		for (j = i+1; j < tpmradix; j++)
		{
			q[j][i] = q[i][j];
		}
	}
} /* rtfdata */

/* transform letter codes to state numbers */
int code2int(cvector c, int *numgaps, int *others)
{	if (data_optn == NUCLEOTIDE) { /* nucleotides */
		if (nuc_optn) { /* 4x4 */
			switch (c[0]) {
				case 'A': return 0;
				case 'C': return 1;
				case 'G': return 2;
				case 'T': return 3;
				case 'U': return 3;
				case '-': (*numgaps)++; return 4;
				default : (*others)++; return 4;
			}
		} /* nuc - 4x4 */

		if (SH_optn) { /* 16x16 */
			if (c[0] == 'A') {
				switch (c[1]) {
					case 'A': return 0; /* AA */
					case 'C': return 1; /* AC */
					case 'G': return 2; /* AG */
					case 'T': return 3; /* AT */
					case 'U': return 3; /* AT */
					case '-': (*numgaps)++; return 16; /* A- */
					default:  (*others)++; return 16;
				}
			}
			if (c[0] == 'C') {
				switch (c[1]) {
					case 'A': return 4; /* CA */
					case 'C': return 5; /* CC */
					case 'G': return 6; /* CG */
					case 'T': return 7; /* CT */
					case 'U': return 7; /* CT */
					case '-': (*numgaps)++; return 16; /* C- */
					default:  (*others)++; return 16;
				}
			}
			if (c[0] == 'G') {
				switch (c[1]) {
					case 'A': return 8; /* GA */
					case 'C': return 9; /* GC */
					case 'G': return 10; /* GG */
					case 'T': return 11; /* GT */
					case 'U': return 11; /* GT */
					case '-': (*numgaps)++; return 16; /* G- */
					default:  (*others)++; return 16;
				}
			}
			if (c[0] == 'T' || c[0] == 'U') {
				switch (c[1]) {
					case 'A': return 12; /* TA */
					case 'C': return 13; /* TC */
					case 'G': return 14; /* TG */
					case 'T': return 15; /* TT */
					case 'U': return 15; /* TT */
					case '-': (*numgaps)++; return 16; /* T- */
					default:  (*others)++; return 16;
				}
			}

                        /* -A, -C, -G, -T, ?A, ?C, ?G, ?T */

			if (c[0] == '-') (*numgaps)++;
                        else             (*others)++;

			if (!((c[1] == 'T') || (c[1] == 'U') || (c[1] == 'T') || (c[1] == 'U'))) {
			   if (c[1] == '-') (*numgaps)++;
			   else             (*others)++;
			}
			return 16;

		} /* SH - 16x16 */
	} else if (data_optn == AMINOACID) { /* amino acids */
		switch (c[0]) {
			case 'A': return 0;
			case 'C': return 4;
			case 'D': return 3;
			case 'E': return 6;
			case 'F': return 13;
			case 'G': return 7;
			case 'H': return 8;
			case 'I': return 9;
			case 'K': return 11;
			case 'L': return 10;
			case 'M': return 12;
			case 'N': return 2;
			case 'P': return 14;
			case 'Q': return 5;
			case 'R': return 1;
			case 'S': return 15;
			case 'T': return 16;
			case 'V': return 19;
			case 'W': return 17;
			case 'Y': return 18;
			case '-': (*numgaps)++; return 20;
			default : (*others)++; return 20;
		}
	} else { /* two-state model - BINARY */
		switch (c[0]) {
			case '0': return 0;
			case '1': return 1;
			case '-': (*numgaps)++; return 2;
			default : (*others)++; return 2;
		}
	} /* two-state model */
	return 0;
} /* code2int */

/* return letter code belonging to state number */
char *int2code(int s)
{
	if (data_optn == 0) { /* nucleotides */
		if (nuc_optn) { /* 4x4 */
			switch (s) {
				case 0: return "A";
				case 1: return "C";
				case 2: return "G";
				case 3: return "T";
				default : return "?";
			}
		}
		if (SH_optn) { /* 16x16 */
			switch (s) {
				case 0: return "AA";
				case 1: return "AC";
				case 2: return "AG";
				case 3: return "AT";
				case 4: return "CA";
				case 5: return "CC";
				case 6: return "CG";
				case 7: return "CT";
				case 8: return "GA";
				case 9: return "GC";
				case 10: return "GG";
				case 11: return "GT";
				case 12: return "TA";
				case 13: return "TC";
				case 14: return "TG";
				case 15: return "TT";
				default : return "??";
			}
		}
	} else if (data_optn == 1) { /* amino acids */
		switch (s) {
			case 0: return "A";
			case 1: return "R";
			case 2: return "N";
			case 3: return "D";
			case 4: return "C";
			case 5: return "Q";
			case 6: return "E";
			case 7: return "G";
			case 8: return "H";
			case 9: return "I";
			case 10: return "L";
			case 11: return "K";
			case 12: return "M";
			case 13: return "F";
			case 14: return "P";
			case 15: return "S";
			case 16: return "T";
			case 17: return "W";
			case 18: return "Y";
			case 19: return "V";
			default : return "?";
		}
	} else { /* two-state model */
		switch (s) {
			case 0: return "0";
			case 1: return "1";
			default : return "?";
		}
	}
	return "?";
} /* int2code */
