void AACodonMutSelSBDPPhyloProcess::ReadPredictedOmega(string name, int burnin, int every, int until)	{

	if (GetNprocs() > 1)	{
		cerr << "error in read predicted omega: works only under non mpi\n";
		exit(1);
	}

	double* meanomega = new double[GetNsite()];
	for (int i=0; i<GetNsite(); i++)	{
		meanomega[i] = 0;
	}
	ifstream is((name + ".chain").c_str());
	if (!is)	{
		cerr << "error: no .chain file found\n";
		exit(1);
	}

	cerr << "burnin : " << burnin << "\n";
	cerr << "until : " << until << '\n';
	int i=0;
	while ((i < until) && (i < burnin))	{
		FromStream(is);
		i++;
	}
	int samplesize = 0;

	while (i < until)	{
		cerr << ".";
		cerr.flush();
		samplesize++;
		FromStream(is);
		i++;

		UpdateMatrices();
		for (int i=0; i<GetNsite(); i++)	{
			meanomega[i] += GetPredictedOmega(i);
		}
		int nrep = 1;
		while ((i<until) && (nrep < every))	{
			FromStream(is);
			i++;
			nrep++;
		}
	}
	cerr << '\n';
	
	double mean = 0;
	ofstream os((name + ".predsiteomega").c_str());
	os << "site\tomega\n";
	for (int i=0; i<GetNsite(); i++)	{
		meanomega[i] /= samplesize;
		mean += meanomega[i];
		os << i+1 << '\t' << meanomega[i] << '\n';
	}
	cerr << "mean site-specific predicted dN/dS in" << name << ".predsiteomega\n";
	mean /= GetNsite();
	cerr << "global mean predicted omega: " << mean << '\n';
	cerr << '\n';
}
bool iDibReader::FromFile(iPaletteDib& dib, const iStringT& fname) const
{ 
	if (!iFile::Exists(fname)) return false;
	IMG_TYPE it;
	if (fname.Right(4).CompareIgnoreCase(_T(".bmp")) == 0) it = IT_BMP;
	else if (fname.Right(4).CompareIgnoreCase(_T(".gif")) == 0) it = IT_GIF;
	else return false;

	iFilePtr pFile = NULL;
	pFile = OpenWin32File(fname);
	if (!pFile) return false;
	bool bRes = FromStream(dib,pFile.get(),it);
	return bRes;
}
void CodonMutSelSBDPPhyloProcess::Read(string name, int burnin, int every, int until)	{

	ifstream is((name + ".chain").c_str());
	if (! is)	{
		cerr << "error: did not find " << name << ".chain\n";
		exit(1);
	}
	//cerr << "In CodonMutSelDPPhyloProcess. GetDim() is : " << GetDim() << "\n";
	int Nstate = CodonMutSelSBDPSubstitutionProcess::GetNstate();
	//cerr << "Nstate is: " << Nstate << "\n";
	//cerr.flush();
	double TOOSMALL = 1e-20;
	int Ncat = 241;
	double min = -30;
	double max = 30;
	double step = 0.25;

	double meanlength = 0;
	double varlength = 0;
	double** PosteriorMeanSiteCodonP = new double*[ProfileProcess::GetNsite()];
	double** sshistoMut = new double*[ProfileProcess::GetNsite()];
	double** sshistoSub = new double*[ProfileProcess::GetNsite()];
	double** sshistoNonsynMut = new double*[ProfileProcess::GetNsite()];
	double** sshistoNonsynSub = new double*[ProfileProcess::GetNsite()];
	double** sshistoSynMut = new double*[ProfileProcess::GetNsite()];
	double** sshistoSynSub = new double*[ProfileProcess::GetNsite()];
	for (int site = 0; site < ProfileProcess::GetNsite(); site++)        {
		PosteriorMeanSiteCodonP[site] = new double[GetDim()];
		sshistoMut[site] = new double[Ncat];
		sshistoSub[site] = new double[Ncat];
		sshistoNonsynMut[site] = new double[Ncat];
		sshistoNonsynSub[site] = new double[Ncat];
		sshistoSynMut[site] = new double[Ncat];
		sshistoSynSub[site] = new double[Ncat];
		for (int a = 0; a < GetDim(); a++)   {
			PosteriorMeanSiteCodonP[site][a] = 0;
		}
		for (int a = 0; a < Ncat; a++)	{
			sshistoMut[site][a] = 0;
			sshistoSub[site][a] = 0;
			sshistoNonsynMut[site][a] = 0;
			sshistoNonsynSub[site][a] = 0;
			sshistoSynMut[site][a] = 0;
			sshistoSynSub[site][a] = 0;
		}
	}
	double* meanNucStat = new double[Nnuc];
	for (int i=0; i<Nnuc; i++)	{
		meanNucStat[i]=0.0;
	}
	double* meanNucRR = new double[Nnucrr];
	for (int i=0; i<Nnucrr; i++)	{
		meanNucRR[i] = 0.0;
	}
	
	double* ghistoMut = new double[Ncat];
	double* ghistoSub = new double[Ncat];
	double* ghistoNonsynMut = new double[Ncat];
	double* ghistoNonsynSub = new double[Ncat];
	double* ghistoSynMut = new double[Ncat];
	double* ghistoSynSub = new double[Ncat];

	double* shistoMut = new double[Ncat];
	double* shistoSub = new double[Ncat];
	double* shistoNonsynMut = new double[Ncat];
	double* shistoNonsynSub = new double[Ncat];
	double* shistoSynMut = new double[Ncat];
	double* shistoSynSub = new double[Ncat];

	double* tsshistoMut = new double[Ncat];
	double* tsshistoSub = new double[Ncat];
	double* tsshistoNonsynMut = new double[Ncat];
	double* tsshistoNonsynSub = new double[Ncat];
	double* tsshistoSynMut = new double[Ncat];
	double* tsshistoSynSub = new double[Ncat];
	for (int c = 0; c < Ncat; c++)	{
		ghistoMut[c] = 0;
		ghistoSub[c] = 0;
		ghistoNonsynMut[c] = 0;
		ghistoNonsynSub[c] = 0;
		ghistoSynMut[c] = 0;
		ghistoSynSub[c] = 0;
	}
	//const double* stat;
	double* stat = new double[Nstate];
	int pos, nucFrom, nucTo, nucRRIndex, c;
	double statMutRate, S, statSubRate, totalMut, totalSub, totalNonsynMut, totalNonsynSub, totalSynMut, totalSynSub, siteTotalMut, siteTotalSub, siteTotalNonsynMut, siteTotalNonsynSub, siteTotalSynMut, siteTotalSynSub, Z;
	cerr << "Ncat is " << Ncat << "\n";
	cerr << "burnin : " << burnin << "\n";
	cerr << "until : " << until << '\n';
	int i=0;
	while ((i < until) && (i < burnin))	{
		cerr << ".";
		cerr.flush();
		FromStream(is);
		i++;
	}
	int samplesize = 0;
	while (i < until)	{
		// cerr << ".";
		cerr.flush();
		samplesize++;
		FromStream(is);
		i++;
		QuickUpdate();
		//UpdateMatrices();
		//Trace(cerr);
		double length = GetTotalLength();
		// int nocc = process->GetNOccupiedComponent();
		meanlength += length;
		varlength += length * length;
		for (int a=0; a<Nnuc; a++)	{
			meanNucStat[a] += GetNucStat(a);
		}
		for (int a=0; a<Nnucrr; a++)	{
			meanNucRR[a] += GetNucRR(a);
		}
		totalMut = 0;
		totalSub = 0;
		totalNonsynMut = 0;
		totalNonsynSub = 0;
		totalSynMut = 0;
		totalSynSub = 0;
		for (c = 0; c < Ncat; c++)	{
			shistoMut[c] = 0;
			shistoSub[c] = 0;
			shistoNonsynMut[c] = 0;
			shistoNonsynSub[c] = 0;
			shistoSynMut[c] = 0;
			shistoSynSub[c] = 0;
		}
		for (int site=0; site<ProfileProcess::GetNsite(); site++)	{
			siteTotalMut = 0;
			siteTotalSub = 0;
			siteTotalNonsynMut = 0;
			siteTotalNonsynSub = 0;
			siteTotalSynMut = 0;
			siteTotalSynSub = 0;
			
			for (c = 0; c < Ncat; c++)	{
				tsshistoMut[c] = 0;
				tsshistoSub[c] = 0;
				tsshistoNonsynMut[c] = 0;
				tsshistoNonsynSub[c] = 0;
				tsshistoSynMut[c] = 0;
				tsshistoSynSub[c] = 0;
			}
			for (int a=0; a<GetDim(); a++)	{
				PosteriorMeanSiteCodonP[site][a] += profile[alloc[site]][a]; 
			}
			Z = 0;
			for (int s=0; s<Nstate; s++)	{
				stat[s] = 	GetNucStat(GetCodonStateSpace()->GetCodonPosition(0, s)) *
						GetNucStat(GetCodonStateSpace()->GetCodonPosition(1, s)) *
						GetNucStat(GetCodonStateSpace()->GetCodonPosition(2, s)) *
						profile[alloc[site]][s];
				Z += stat[s];
			}
			for (int s=0; s<Nstate; s++)	{
				stat[s] /= Z;
			}
			//stat = GetStationary(site);
			//stat = matrixarray[alloc[site]]->GetStationary();
			for (int codonFrom = 0; codonFrom<Nstate; codonFrom++)	{
				for (int codonTo = 0; codonTo<Nstate; codonTo++)	{
					pos = GetCodonStateSpace()->GetDifferingPosition(codonFrom, codonTo);				
					if ((pos != -1) && (pos != 3))  {
						nucFrom = GetCodonStateSpace()->GetCodonPosition(pos, codonFrom);
						nucTo = GetCodonStateSpace()->GetCodonPosition(pos, codonTo);
						if (nucFrom<nucTo)	{
							nucRRIndex = (2 * Nnuc - nucFrom - 1) * nucFrom / 2 + nucTo - nucFrom - 1;
						}
						else {
							nucRRIndex = (2 * Nnuc - nucTo - 1) * nucTo / 2 + nucFrom - nucTo - 1;
						}
						statMutRate = GetNucRR(nucRRIndex) * GetNucStat(nucTo) * stat[codonFrom];
						S = log(profile[alloc[site]][codonTo]/profile[alloc[site]][codonFrom]);

						if (fabs(S) < TOOSMALL)	{
							statSubRate = statMutRate * 1.0/( 1.0 - (S / 2) );
						}
						else {
							statSubRate = statMutRate * (S/(1-(profile[alloc[site]][codonFrom]/profile[alloc[site]][codonTo])));
						}
						if (S < min)	{
							c = 0;
						}
						else if (S > max)	{
							c = Ncat-1;
						}
						else {
							c = 0;
							double tmp = min + ((double)c * step) - step/2 + step;
							do	{
								c++;
								tmp = min + ((double)(c) * step) - step/2 + step;
							} while (tmp < S );
						}
						if (c == Ncat)	{
							cout << "error, c==Ncat.\n";
							cout.flush();
						}
	
						shistoMut[c] += statMutRate;
						shistoSub[c] += statSubRate;
						tsshistoMut[c] += statMutRate;
						tsshistoSub[c] += statSubRate;
						if (!GetCodonStateSpace()->Synonymous(codonFrom, codonTo))	{
							shistoNonsynMut[c] += statMutRate;
							shistoNonsynSub[c] += statSubRate;
							totalNonsynMut += statMutRate;
							totalNonsynSub += statSubRate;

							tsshistoNonsynMut[c] += statMutRate;
							tsshistoNonsynSub[c] += statSubRate;
							siteTotalNonsynMut += statMutRate;
							siteTotalNonsynSub += statSubRate;
						}
						else	{
							shistoSynMut[c] += statMutRate;
							shistoSynSub[c] += statSubRate;
							totalSynMut += statMutRate;
							totalSynSub += statSubRate;

							tsshistoSynMut[c] += statMutRate;
							tsshistoSynSub[c] += statSubRate;
							siteTotalSynMut += statMutRate;
							siteTotalSynSub += statSubRate;
							
						}
						totalMut += statMutRate;
						totalSub += statSubRate;
						siteTotalMut += statMutRate;
						siteTotalSub += statSubRate;
					}
				}
			}

			for (c=0; c<Ncat; c++)	{
				sshistoMut[site][c] += tsshistoMut[c]/siteTotalMut;
				sshistoSub[site][c] += tsshistoSub[c]/siteTotalSub;
				sshistoNonsynMut[site][c] += tsshistoNonsynMut[c]/siteTotalNonsynMut;
				sshistoNonsynSub[site][c] += tsshistoNonsynSub[c]/siteTotalNonsynSub;
				sshistoSynMut[site][c] += tsshistoSynMut[c]/siteTotalSynMut;
				sshistoSynSub[site][c] += tsshistoSynSub[c]/siteTotalSynSub;
			}
		}	

		for (c=0; c<Ncat; c++)	{
			ghistoMut[c] += shistoMut[c]/totalMut;
			ghistoSub[c] += shistoSub[c]/totalSub;
			ghistoNonsynMut[c] += shistoNonsynMut[c]/totalNonsynMut;
			ghistoNonsynSub[c] += shistoNonsynSub[c]/totalNonsynSub;
			ghistoSynMut[c] += shistoSynMut[c]/totalSynMut;
			ghistoSynSub[c] += shistoSynSub[c]/totalSynSub;
		}

		int nrep = 1;
		while ((i<until) && (nrep < every))	{
			FromStream(is);
			i++;
			nrep++;
		}
	}
	cerr << '\n';
	meanlength /= samplesize;
	varlength /= samplesize;
	varlength -= meanlength * meanlength;

	cerr << "mean length : " << meanlength << " +/- " << sqrt(varlength) << '\n';

	double* ppvhistoMut = new double[Ncat];
	double* ppvhistoSub = new double[Ncat];
	double* ppvhistoNonsynMut = new double[Ncat];
	double* ppvhistoNonsynSub = new double[Ncat];
	for (c=0; c<Ncat; c++)	{
		ppvhistoMut[c] = 0;
		ppvhistoSub[c] = 0;
		ppvhistoNonsynMut[c] = 0;
		ppvhistoNonsynSub[c] = 0;
	}
	
	totalMut = 0;
	totalSub = 0;
	totalNonsynMut = 0;
	totalNonsynSub = 0;

	ofstream codonp_os( (name + ".codonp").c_str(), std::ios::out);
	for (int site=0; site<ProfileProcess::GetNsite(); site++)	{
		for (int a=0; a<GetDim(); a++)	{
			codonp_os << PosteriorMeanSiteCodonP[site][a] / samplesize << "\t";
		}
		codonp_os << "\n";

		Z = 0;
		for (int s=0; s<Nstate; s++)	{
			stat[s] = 	(meanNucStat[GetCodonStateSpace()->GetCodonPosition(0, s)] *
					meanNucStat[GetCodonStateSpace()->GetCodonPosition(1, s)] *
					meanNucStat[GetCodonStateSpace()->GetCodonPosition(2, s)] *
					PosteriorMeanSiteCodonP[site][s]) / samplesize;
			Z += stat[s];
		}
		for (int s=0; s<Nstate; s++)	{
			stat[s] /= Z;
		}
		for (int codonFrom = 0; codonFrom<Nstate; codonFrom++)	{
			for (int codonTo = 0; codonTo<Nstate; codonTo++)	{
				pos = GetCodonStateSpace()->GetDifferingPosition(codonFrom, codonTo);				
				if ((pos != -1) && (pos != 3))  {
					nucFrom = GetCodonStateSpace()->GetCodonPosition(pos, codonFrom);
					nucTo = GetCodonStateSpace()->GetCodonPosition(pos, codonTo);
					if (nucFrom<nucTo)	{
						nucRRIndex = (2 * Nnuc - nucFrom - 1) * nucFrom / 2 + nucTo - nucFrom - 1;
					}
					else {
						nucRRIndex = (2 * Nnuc - nucTo - 1) * nucTo / 2 + nucFrom - nucTo - 1;
					}
					statMutRate = meanNucRR[nucRRIndex] * meanNucStat[nucTo] * stat[codonFrom];
					double expS = (PosteriorMeanSiteCodonP[site][codonTo]/samplesize)/(PosteriorMeanSiteCodonP[site][codonFrom]/samplesize);
					S = log(expS);
					statSubRate = statMutRate * (S/(1-((PosteriorMeanSiteCodonP[site][codonFrom]/samplesize)/(PosteriorMeanSiteCodonP[site][codonTo]/samplesize))));
					if (S < min)	{
						c = 0;
					}
					else if (S > max)	{
						c = Ncat-1;
					}
					else {
						c = 0;
						double tmp = min + ((double)c * step) - step/2 + step;
						do	{
							c++;
							tmp = min + ((double)(c) * step) - step/2 + step;
						} while (tmp < S );
					}
					if (c == Ncat)	{
						cout << "error, c==Ncat.\n";
						cout.flush();
					}

					ppvhistoMut[c] += statMutRate;
					ppvhistoSub[c] += statSubRate;
					if (!GetCodonStateSpace()->Synonymous(codonFrom, codonTo))	{
						ppvhistoNonsynMut[c] += statMutRate;
						ppvhistoNonsynSub[c] += statSubRate;
						totalNonsynMut += statMutRate;
						totalNonsynSub += statSubRate;
					}
					totalMut += statMutRate;
					totalSub += statSubRate;
				}
			}
		}
	}	

	
	ofstream mutmutsel_os( (name + ".mutsel").c_str(), std::ios::out);
	ofstream mutsubsel_os( (name + ".subsel").c_str(), std::ios::out);
	ofstream nonsynmutmutsel_os( (name + ".nonsynmutsel").c_str(), std::ios::out);
	ofstream nonsynmutsubsel_os( (name + ".nonsynsubsel").c_str(), std::ios::out);
	ofstream synmutmutsel_os( (name + ".synmutsel").c_str(), std::ios::out);
	ofstream synmutsubsel_os( (name + ".synsubsel").c_str(), std::ios::out);

	ofstream sitemutmutsel_os( (name + ".sitemutsel").c_str(), std::ios::out);
	ofstream sitemutsubsel_os( (name + ".sitesubsel").c_str(), std::ios::out);
	ofstream sitenonsynmutmutsel_os( (name + ".sitenonsynmutsel").c_str(), std::ios::out);
	ofstream sitenonsynmutsubsel_os( (name + ".sitenonsynsubsel").c_str(), std::ios::out);
	ofstream sitesynmutmutsel_os( (name + ".sitesynmutsel").c_str(), std::ios::out);
	ofstream sitesynmutsubsel_os( (name + ".sitesynsubsel").c_str(), std::ios::out);

	ofstream ppvmutmutsel_os( (name + ".ppvmutsel").c_str(), std::ios::out);
	ofstream ppvmutsubsel_os( (name + ".ppvsubsel").c_str(), std::ios::out);
	ofstream ppvnonsynmutmutsel_os( (name + ".ppvnonsynmutsel").c_str(), std::ios::out);
	ofstream ppvnonsynmutsubsel_os( (name + ".ppvnonsynsubsel").c_str(), std::ios::out);
	for (c = 0; c < Ncat; c++)	{
		mutmutsel_os << (min + (c * step)) << "\t" << (ghistoMut[c]/samplesize) << '\n';
		mutsubsel_os << (min + (c * step)) << "\t" << (ghistoSub[c]/samplesize) << '\n';
		nonsynmutmutsel_os << (min + (c * step)) << "\t" << (ghistoNonsynMut[c]/samplesize) << '\n';
		nonsynmutsubsel_os << (min + (c * step)) << "\t" << (ghistoNonsynSub[c]/samplesize) << '\n';
		synmutmutsel_os << (min + (c * step)) << "\t" << (ghistoSynMut[c]/samplesize) << '\n';
		synmutsubsel_os << (min + (c * step)) << "\t" << (ghistoSynSub[c]/samplesize) << '\n';

		ppvmutmutsel_os << (min + (c * step)) << "\t" << (ppvhistoMut[c]/totalMut) << '\n';
		ppvmutsubsel_os << (min + (c * step)) << "\t" << (ppvhistoSub[c]/totalSub) << '\n';
		ppvnonsynmutmutsel_os << (min + (c * step)) << "\t" << (ppvhistoNonsynMut[c]/totalNonsynMut) << '\n';
		ppvnonsynmutsubsel_os << (min + (c * step)) << "\t" << (ppvhistoNonsynSub[c]/totalNonsynSub) << '\n';
		for (int site = 0; site < ProfileProcess::GetNsite(); site++)	{
			if (site == 0) 	{
				sitemutmutsel_os << (min + (c * step)) << '\t' << (sshistoMut[site][c]/samplesize) << '\t';
				sitemutsubsel_os << (min + (c * step)) << '\t' << (sshistoSub[site][c]/samplesize) << '\t';
				sitenonsynmutmutsel_os << (min + (c * step)) << '\t' << (sshistoNonsynMut[site][c]/samplesize) << '\t';
				sitenonsynmutsubsel_os << (min + (c * step)) << '\t' << (sshistoNonsynSub[site][c]/samplesize) << '\t';
				sitesynmutmutsel_os << (min + (c * step)) << '\t' << (sshistoSynMut[site][c]/samplesize) << '\t';
				sitesynmutsubsel_os << (min + (c * step)) << '\t' << (sshistoSynSub[site][c]/samplesize) << '\t';
			}
			else if (site == ProfileProcess::GetNsite() - 1)	{
				sitemutmutsel_os << (sshistoMut[site][c]/samplesize) << '\n';
				sitemutsubsel_os << (sshistoSub[site][c]/samplesize) << '\n';
				sitenonsynmutmutsel_os << (sshistoNonsynMut[site][c]/samplesize) << '\n';
				sitenonsynmutsubsel_os << (sshistoNonsynSub[site][c]/samplesize) << '\n';
				sitesynmutmutsel_os << (sshistoSynMut[site][c]/samplesize) << '\n';
				sitesynmutsubsel_os << (sshistoSynSub[site][c]/samplesize) << '\n';
			}
			else {
				sitemutmutsel_os << (sshistoMut[site][c]/samplesize) << '\t';
				sitemutsubsel_os << (sshistoSub[site][c]/samplesize) << '\t';
				sitenonsynmutmutsel_os << (sshistoNonsynMut[site][c]/samplesize) << '\t';
				sitenonsynmutsubsel_os << (sshistoNonsynSub[site][c]/samplesize) << '\t';
				sitesynmutmutsel_os << (sshistoSynMut[site][c]/samplesize) << '\t';
				sitesynmutsubsel_os << (sshistoSynSub[site][c]/samplesize) << '\t';
			}
		}
	}

	cerr << samplesize << '\n';
	for (int site = 0; site < GetNmodeMax(); site++)        {
		delete[] PosteriorMeanSiteCodonP[site];
		delete[] sshistoMut[site];
		delete[] sshistoSub[site];
		delete[] sshistoNonsynMut[site];
		delete[] sshistoNonsynSub[site];
		delete[] sshistoSynMut[site];
		delete[] sshistoSynSub[site];
	}
	delete[] PosteriorMeanSiteCodonP;
	delete[] sshistoMut;
	delete[] sshistoSub;
	delete[] sshistoNonsynMut;
	delete[] sshistoNonsynSub;
	delete[] sshistoSynMut;
	delete[] sshistoSynSub;
	delete[] tsshistoMut;
	delete[] tsshistoSub;
	delete[] tsshistoNonsynMut;
	delete[] tsshistoNonsynSub;
	delete[] tsshistoSynMut;
	delete[] tsshistoSynSub;
	delete[] ghistoMut;
	delete[] ghistoSub;
	delete[] ghistoNonsynMut;
	delete[] ghistoNonsynSub;
	delete[] ghistoSynMut;
	delete[] ghistoSynSub;
	delete[] shistoMut;
	delete[] shistoSub;
	delete[] shistoNonsynMut;
	delete[] shistoNonsynSub;
	delete[] shistoSynMut;
	delete[] shistoSynSub;
	delete[] ppvhistoMut;
	delete[] ppvhistoSub;
	delete[] ppvhistoNonsynMut;
	delete[] ppvhistoNonsynSub;
	delete[] stat;
	delete[] meanNucStat;
	delete[] meanNucRR;
}
void AACodonMutSelSBDPPhyloProcess::ReadMapStats(string name, int burnin, int every, int until){
  	ifstream is((name + ".chain").c_str());
	if (!is)	{
		cerr << "error: no .chain file found\n";
		exit(1);
	}
	cerr << "burnin : " << burnin << "\n";
	cerr << "until : " << until << '\n';
	int i=0;
	while ((i < until) && (i < burnin))	{
		FromStream(is);
		i++;
	}

	
	ofstream ospost((name + ".nonsynpost").c_str());
	ofstream ospred((name + ".nonsynpred").c_str());
	ofstream ospvalue((name + ".nonsynpvalue").c_str());

	int samplesize = 0;
	int pvalue=0;
	int obs, pred;
	while (i < until)	{
		cerr << ".";
		cerr.flush();
		samplesize++;
		FromStream(is);
		i++;

		MPI_Status stat;
		MESSAGE signal = BCAST_TREE;
		MPI_Bcast(&signal,1,MPI_INT,0,MPI_COMM_WORLD);
		GlobalBroadcastTree();
		GlobalUpdateConditionalLikelihoods();
		GlobalCollapse();

		GlobalUpdateSiteProfileSuffStat();

		// write posterior
		obs = GlobalNonSynMapping();
		ospost << (double) (obs) / AACodonMutSelProfileProcess::GetNsite() << "\n";
		cerr << (double) (obs) / AACodonMutSelProfileProcess::GetNsite() << "\t";

		GlobalUnfold();

		//Posterior Prededictive Mappings
		GlobalUnclamp();
		GlobalCollapse();
		GlobalUpdateSiteProfileSuffStat();
		GlobalSetDataFromLeaves();

		// write posterior predictive
		pred = GlobalNonSynMapping();
		ospred << (double) (pred) / AACodonMutSelProfileProcess::GetNsite() << "\n";
		cerr << (double) (pred) / AACodonMutSelProfileProcess::GetNsite() << "\n";
	
		if (pred > obs) pvalue++;

		GlobalRestoreData();
		GlobalUnfold();

		int nrep = 1;
		while ((i<until) && (nrep < every))	{
			FromStream(is);
			i++;
			nrep++;
		}
	}

	ospvalue << (double) (pvalue) / samplesize << "\n";
	cerr << '\n';
}
void AACodonMutSelSBDPPhyloProcess::ReadSiteProfiles(string name, int burnin, int every, int until)	{

	double** sitestat = new double*[GetNsite()];
	for (int i=0; i<GetNsite(); i++)	{
		sitestat[i] = new double[GetDim()];
		for (int k=0; k<GetDim(); k++)	{
			sitestat[i][k] = 0;
		}
	}
	ifstream is((name + ".chain").c_str());
	if (!is)	{
		cerr << "error: no .chain file found\n";
		exit(1);
	}

	cerr << "burnin : " << burnin << "\n";
	cerr << "until : " << until << '\n';
	int i=0;
	while ((i < until) && (i < burnin))	{
		FromStream(is);
		i++;
	}
	int samplesize = 0;

	while (i < until)	{
		cerr << ".";
		cerr.flush();
		samplesize++;
		FromStream(is);
		i++;

		for (int i=0; i<GetNsite(); i++)	{
			double* p = GetProfile(i);
			for (int k=0; k<GetDim(); k++)	{
				sitestat[i][k] += p[k];
			}
		}
		int nrep = 1;
		while ((i<until) && (nrep < every))	{
			FromStream(is);
			i++;
			nrep++;
		}
	}
	cerr << '\n';
	
	ofstream os((name + ".siteprofiles").c_str());
	/*
	if (GetDim() != Naa)	{
		cerr << "error in read site profiles: should be 20 states\n";
		exit(1);
	}
	for (int k=0; k<GetDim(); k++)	{
		os << AminoAcids[k] << ' ';
	}
	os << '\n';
	os << '\n';
	*/
	os << GetNsite() << '\n';
	for (int i=0; i<GetNsite(); i++)	{
		os << i+1;
		for (int k=0; k<GetDim(); k++)	{
			sitestat[i][k] /= samplesize;
			os << '\t' << sitestat[i][k];
		}
		os << '\n';
	}
	cerr << "mean site-specific profiles in " << name << ".siteprofiles\n";
	cerr << '\n';
}