/******************************************************************
* Filename: base.h
* Abstract: base class, including several functions and variables

* Version: 1.7
* Author: Zhang Zhang  (zhangzhang.cn@gmail.com)
* Date: July 26, 2011
* Note: Add an option to output posterior distribution for each gene.

* Version: 1.6
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: Jun. 3, 2011
* Note: Remove the bug for calcuating p-values.

* Version: 1.5
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: Mar. 8, 2011
* Note: (1) Remove the bug when first column count=0, resulting from locating
        the lowest value and normarlization (getPQResults).
		(2) Provide more specifica error message for the input file (setHeader
		and Run). 

* Version: 1.4
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: Nov. 9, 2010
* Note: Remove the bug for normalizing of p.

* Version: 1.3
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: Nov. 1, 2010
* Note: Set q=1 for any input file with only one methodology.

* Version: 1.2
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: July, 2010
* Note: (1) Accommodate input file with only one methodology;
        (2) Update the LOX reference published in Bioinformatics.

* Version: 1.1
* Author: Zhang Zhang  (zhang.zhang@kaust.edu.sa)
* Date: April, 2010
* Note: Output pvalue files

* Version: 1.0
* Author: Zhang Zhang  (zhang.zhang@yale.edu)
* Date: August 27, 2009

* Note: 
LOX is distributed as open-source software and licensed under the GNU 
General Public License (Version 3; http://www.gnu.org/licenses/gpl.txt), 
in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details. Commercial use of LOX 
requires a special contract.

******************************************************************/
#pragma warning(disable:4786)		//Disable warning when using vector

#if !defined(BASE_H)
#define  BASE_H

#define CODONLENGTH 3			//Length of codon
#define DNASIZE 4				//A C G T
#define XSIZE DNASIZE*DNASIZE   //Size of one group AXX (X=A,C,G,T) 
#define CODON 64				//Codon Size
#define NULL 0					//Zero
#define NA -1					//Not Available
#define NCODE	23				//Number of genetic codes
#define NNCODE  NCODE*2			//Double of the number genetic codes		
#define SMALLVALUE 1e-30		//Value near to zero
#define NUMBER_OF_RATES	6		//Number of substitution rates
#define MODELCOUNT	14			//Number of candidate models

#define gammap(x,alpha) (alpha*(1-pow(x,-1/alpha)))
#define square(a) ((a)*(a))

#define min2(a,b) ((a)<(b)?(a):(b))
#define max2(a,b) ((a)>(b)?(a):(b))
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
#define Pi 3.1415956

#define ENDCONCAT "EndOfStringConcat"	//for funcation concat
#define DECIMAL_POINT '.'

/* Stanard lib of C++ */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<cstdlib>
#include<limits>
#include<string>
#include<cctype>
#include<algorithm>

#include<stdlib.h>
#include<stdio.h>
#include<stdarg.h>
#include<math.h>
#include<time.h>
#include<ctype.h>
//OS-dependent libraries
#ifdef WIN32
	#include<direct.h>
#else 
	#include<sys/stat.h>
	#include<sys/types.h>
	#include<unistd.h>
#endif

using namespace std;

/*****Global variables*****/
extern const char* transl_table[];	//Genetic codon table
extern int genetic_code;			//ID of codon table from 1 to 23

//End of Global variables


/* Convert one type to any other type */
template<class out_type,class in_value>
	out_type CONVERT(const in_value & t) {
		stringstream stream;
		//Put the value 't' into the stream
		stream<<t;			
		out_type result;
		//Put the stream into the 'result'
		stream>>result;

		return result;
	}

class Base {

public:
	/* Set current time as random seed */
	Base();	

	/* Write the content into file */
	bool writeFile(string output_filename, const char* result, int show_filename=1);

	/* Parse results */
	string parseOutput();	
	/* Format string for outputing into file */
	void addString(string &result, string str, string flag="\t");
	string concat(const char* fmt, ...);

	/* Generate a radnom integer */
	int getRandom();
	double getRand0to1();
	int getRandLow2High(int lowbound, int highbound);
	double getRandNeg1toPos1();

	string format(double value, int decplaces=3);
	
	int countChar(string str, char ch);
	
	/* Convert a char-T,C,A,G into a digit 0,1,2,3, respectively */
	int  convertChar(char ch);
	/* Convert a digit-0,1,2,3 into a char T,C,A,G, respectively */
	char convertInt(int ch);
	/* Convert a string to uppercase */
	string stringtoUpper(string str);
	vector<string> splitString(string str, char delims='\t');

	string trim(string str);
	string filterString(string str);
	
	string replaceAll(string str, char from, char to);
	string replaceAll(string str, char from);
	
	string toString(char ch);
	string toString(int ch);
	string toString(long ch);
	string toString(double ch);
	string toString(bool boolflag);
	char toChar(int);

	/* Calculate the amino acid of codon by codon */
	char getAminoAcid(string codon);
	/* Calculate the amino acid of codon by codon's id*/
	char getAminoAcid(int id);
	/* Get the number of stop codon in a given genetic code table */
	int getNumNonsense(int genetic_code);

	/* Return the codon's id from codon table */
	int getID(string codon);
	/* Return a codon according to the id */
	string getCodon(int IDcodon);

	/* Sum array's elements */
	double sumArray(double x[], int end, int begin=0);
	int sumArray(int x[], int end, int begin=0);

	/* Init value to array */
	int initArray(double x[], int n, double value=0.0);
	int initArray(int x[], int n, int value=0);

	/* Elements in array are mutipled by scale */
	int scaleArray(double scale, double x[], int n);
	/* Sqrt of the sum of the elements' square */
	double norm(double x[], int n);
	/* Copy array's values one by one: to[] = from[] */
	int copyArray(double from[], double to[], int n);
	int copyVector(vector<double> from, vector<double> &to);	

	/* Sum of 'n' products multiplied by two elements x[], y[] */
	double innerp(double x[], double y[], int n);
	/* Set x[i,j]=0 when x!=j and x[i,j]=1 when x=j */
	int initIdentityMatrix(double x[], int n);

	bool removeCntrl(string name, vector<string> &str);
	bool checkValid(string name, vector<string> &str);
	int readAXT(string seqfile, vector<string> &seqname, vector<string> &seq);
	int readFasta(string seqfile, vector<string> &seqname, vector<string> &seq);
	string generalInput(vector<string> seq);
	string RGB(int r, int g, int b);

	//Format time as hh:mm:ss
	string formatDateTime(time_t t);

private:
	unsigned long Seed;
	
};

#endif


