/***************************************************************************
 applpopulations.cpp  -  description
 -------------------
 begin                : Mon Oct 30 2000
 copyright            : (C) 2000 by Olivier Langella
 email                : Olivier.Langella@pge.cnrs-gif.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "applpopulations.h"

ApplPopulations::ApplPopulations() :
	ApplPop() {
	_square_distance = false;
}

ApplPopulations::~ApplPopulations() {
}

int ApplPopulations::menu_principal() {
	// calcul de distance entre tous les individus de n pop
	int choix;
	_choix = 0;

	cout << endl << endl;
	cout << _("Main menu") << endl << endl;
	cout << "0) " << _("Exit") << endl;
	cout << "1) " << _("Compute individuals distances + tree") << endl;
	cout << "2) " << _("Compute populations distances + tree") << endl;
	cout << "3) " << _("Allelic frequencies, Fstats") << endl;
	cout << "4) " << _("Build phylogenetic tree with a distance matrix")
			<< endl;
	cout << "5) " << _("Formated output for other softwares") << endl;
	cout << "6) " << _("Choose the output format of matrix") << endl;
	cout << "7) " << _("Structured populations") << endl;
	cout << "8) " << _("microsatellites number of repeats corrections") << endl;
	//	cout << "8) Concatenation de populations" << endl;

	choix = DemandeChoix(0, 8);

	switch (choix) {
	case 0:
		return (0);
		break;
	case 1:
		if (!iPopulations())
			return (1);
		menu_arbreind();
		return (1);
		break;

	case 2:
		if (!iPopulations())
			return (1);
		menu_arbrepop();
		return (2);
		break;

	case 3:
		if (!iPopulations())
			return (1);
		menu_calculs();
		return (3);
		break;

	case 4:
		cout << endl << endl;
		cout << _("Build phylogenetic tree with a distance matrix") << endl;
		//		cout << " a partir d'une matrice de distance" << endl;
		fmat2arbre();
		return (4);
		break;

	case 5:
		if (!iPopulations())
			return (1);
		menu_formats();
		return (5);
		break;

	case 6:
		menu_formatMatrice();
		return (6);
		break;

	case 7:
		if (!iPopulations())
			return (7);
		menu_popstructurees();
		return (7);
		break;

	case 8:
		if (!iPopulations())
			return (8);
		fmicrosatcorrections();
		return (7);
		break;

		/*	case 8:
		 if (!iPopulations()) return(8);
		 cout << endl << endl;
		 //		cout << "Format de sortie des matrices:" << endl;
		 fconcatenationpop();
		 return(8);
		 break;
		 */
	default:
		return (0);
		break;
	}
}

void ApplPopulations::fdistind() {
	MatriceLD distances;
	string nomFichier;

	nomFichier = DemandeFichier("Individuals distance matrix filename :");

	if (fcompdistind(distances) == false)
		return;

	ecritMatriceLD(distances, nomFichier);
}

void ApplPopulations::ftreeind() {
	MatriceLD distances;
	string nomFichier;
	int metdist;
	int metconstruct;
	//	unsigned int i;

	metdist = menu_metdistpop();
	if (_choix == -1)
		return;

	metconstruct = menu_metconstructarbre();
	if (_choix == -1)
		return;

	nomFichier = DemandeFichier("Individuals tree filename (Phylip format):");

	if (fcompdistind(distances, metdist) == false)
		return;

	fconstructarbre(distances, nomFichier, metconstruct);

	cout << _("Phylogenetic tree saved in : ") << nomFichier << endl;
}

void ApplPopulations::ftreeindBootLocus() {
	MatriceLD distances;
	int metdist;
	int metconstructarbre;
	ArbrePlus larbre;

	larbre._titre.resize(2);
	larbre._titre[0].assign(""); // individus, populations
	larbre._titre[1].assign(""); // m�thode de distance, nb bootstrap

	metdist = menu_metdistpop();
	if (_choix == -1)
		return;

	cout << _("Computing distances between individuals...") << endl;
	larbre._titre[0].AjEntier(_Pjeupop->get_nbind());
	larbre._titre[0] += " inidividuals, ";
	larbre._titre[0].AjEntier(_Pjeupop->get_nbpop());
	larbre._titre[0] += " populations";

	larbre._titre[1] += DistancesGnt::get_nom_methode(metdist);

	int nbtirages;

	metconstructarbre = menu_metconstructarbre();
	nbtirages = DemandeEntier(
			_("How many times do you want to perform bootstraps ?"), 1,
			30000);

	larbre._titre[1] += ", ";
	larbre._titre[1].AjEntier(nbtirages);
	larbre._titre[1] += " bootstraps on locus";

	//	cout << _("Output file name (Phylip tree format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier("Output file name (Phylip tree format) ?");

	if (_VcalcLocus.size() == 0)
		_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
				_square_distance, nbtirages, true);
	else
		_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
				_square_distance, nbtirages, true, &_VcalcLocus);
	//	_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist, nbtirages, true);

	//	larbre.fElimineTrifurcation();
	ecritArbre(larbre, _nomFichier);
}

void ApplPopulations::fsetniveau() {
	// r�glage du niveau de structure pour calculs sur des m�tapops

	_niveau = DemandeEntier(_("Which level ?"), 1, 100);

	_Pjeupop->f_rempliVcalcStrucPop(_niveau);

	cerr << "ApplPopulations::fsetniveau() 1" << _VcalcLocus.size() << endl;
	cout << _("level has been set to: ") << _niveau << endl;
	cout << _("any compute using metapopulation will use this") << endl;
	cout << _("(ex: computing distances or making trees") << endl;

}

void ApplPopulations::fmat2arbre() {
	// calcul de distance entre tous les individus de n pop
	MatriceLD distances;
	string nomficarbre("");

	cout << _("Reading distance matrix: ") << endl;
	while (litMatriceLD(distances) == false) {
		//		cout << "Lecture en cours..."<< endl;
	}

	//cerr << "ApplPopulations::fmat2arbre " << distances.GetNC() << " " << distances.GetNL() << endl;

	try {

		/*
		 if (distances.GetType() != 2) {
		 long i, j;
		 for (i = 0; i < distances.GetNC(); i++) {
		 for (j = 0; j < i; j++) {
		 distances.GetCase(j, i) = distances.GetCase(i, j);
		 }
		 }
		 distances.SetType(2);
		 }
		 */
		if (distances.SetType(2) == false) {
			throw biolib::vecteurs::MatriceLD::Anomalie(5);
		}

		//cerr << "ApplPopulations::fmat2arbre" << endl;
		//distances.oExcel(cout);
		fconstructarbre(distances, nomficarbre, menu_metconstructarbre());
	} catch (MatriceLD::Anomalie pb) {
		_fichier.close();
		switch (pb.le_pb) {
		case 1:
			_fichier.close();
			cout << _("Error while reading the matrix file");
			break;

		case 5:
			cerr
					<< _("Failure reading matrix file : the matrix is not symetric\n");
			cerr
					<< _("Populations only works with euclidian distance matrix\n");
			cerr << _("Please check your file and retry\n\n");
			break;
		case 7:
			cout << _("Out of range access in the matrix");
			break;
		}
	}

}

void ApplPopulations::frarefaction() {
	MatriceLD distances;
	int taille;

	//cerr << _Pjeupop->get_nbpop();
	taille = DemandeEntier(_("Sample size ?"), 2, 1000);

	cout << _("Computing...") << endl;
	_Pjeupop->f_rarefaction(distances, taille);

	cout << _("Results matrix output :") << endl;

	//	cerr << distances.GetCase (1,1);
	ecritMatriceLD(distances);
}

bool ApplPopulations::fcompdistind(MatriceLD & distances, int metdist) {
	_temp.resize(2);
	_temp[0].assign(""); // individus, populations
	_temp[1].assign(""); // m�thode de distance, nb bootstrap

	if (metdist == 0) {
		metdist = menu_metdistpop();
		if (_choix == -1)
			return (false);
	}

	cout << _("Computing distances between individuals...") << endl;
	_temp[0].AjEntier(_Pjeupop->get_nbind());
	_temp[0] += " inidividuals, ";
	_temp[0].AjEntier(_Pjeupop->get_nbpop());
	_temp[0] += " populations";

	_temp[1] += DistancesGnt::get_nom_methode(metdist);

	if (_VcalcLocus.size() == 0)
		_Pjeupop->f_distgnt(distances, metdist, _square_distance);
	else
		_Pjeupop->f_distgnt(distances, metdist, _square_distance, &_VcalcLocus);

	return (true);
}

bool ApplPopulations::fcompdistpop(MatriceLD & distances, int metdist) {
	// calcul de distance entre toutes les populations
	_temp.resize(2);
	_temp[0].assign(""); // individus, populations
	_temp[1].assign(""); // m�thode de distance, nb bootstrap

	if (metdist == 0) {
		metdist = menu_metdistpop();
		if (_choix == -1)
			return (false);
	}

	cout << _("Computing distances between populations...") << endl;
	_temp[0].AjEntier(_Pjeupop->get_nbpop());
	_temp[0] += " populations";

	_temp[1] += DistancesGnt::get_nom_methode(metdist);

	try {
		//cerr << "ApplPopulations::fcompdistpop(MatriceLD & distances, int metdist) 1" <<  _VcalcLocus.size() << endl;
		if (_VcalcLocus.size() == 0) {
			//cerr << "ApplPopulations::fcompdistpop(MatriceLD & distances, int metdist) niveau " <<  _niveau << endl;
			_Pjeupop->f_distgntpop(distances, metdist, _square_distance,
					_niveau);
		} else {
			_Pjeupop->f_distgntpop(distances, metdist, _square_distance,
					_niveau, &_VcalcLocus);
		}
	} catch (Jeupop::Anomalie lepb) {
		//		cerr << endl << lepb.fmessage() << endl;
		return (false);
	}

	return (true);
}

void ApplPopulations::fdistpop() {
	// sortie des distance entre toutes les populations
	MatriceLD distances;
	string nomFichier;

	nomFichier = DemandeFichier(_("Populations distance matrix filename :"));

	if (fcompdistpop(distances) == false)
		return;

	ecritMatriceLD(distances, nomFichier);
}

void ApplPopulations::ftreepop() {
	// sortie de l'arbre phylogenetic des pops
	MatriceLD distances;
	string nomFichier;
	int metdist;
	int metconstruct;

	metdist = menu_metdistpop();
	if (_choix == -1)
		return;

	metconstruct = menu_metconstructarbre();
	if (_choix == -1)
		return;

	nomFichier
			= DemandeFichier(_("Populations tree filename (Phylip format):"));

	if (fcompdistpop(distances, metdist)) {
		fconstructarbre(distances, nomFichier, metconstruct);

		cout << _("Phylogenetic tree saved in : ") << nomFichier << endl;
	} else {
		cout
				<< _("Phylogenetic tree reconstruction aborted, tree file was not written")
				<< endl;
	}
}

void ApplPopulations::ftreepopBootLocus() {
	// calcul de distance entre toutes les populations
	// avec bootstrap sur les locus
	MatriceLD distances;
	int metdist;
	int metconstructarbre;

	ArbrePlus larbre;
	int nbtirages;

	metdist = menu_metdistpop();
	if (_choix == -1) {
		_choix = 1;
		return;
	}

	metconstructarbre = menu_metconstructarbre();
	nbtirages = DemandeEntier("Combien de tirages voulez-vous effectuer ?", 1,
			10000);

	larbre._titre.resize(2);
	larbre._titre[0].assign(""); // individus, populations
	larbre._titre[1].assign(""); // m�thode de distance, nb bootstrap

	larbre._titre[0].AjEntier(_Pjeupop->get_nbpop());
	larbre._titre[0] += " populations";

	larbre._titre[1] += DistancesGnt::get_nom_methode(metdist);
	larbre._titre[1] += ", ";
	larbre._titre[1].AjEntier(nbtirages);
	larbre._titre[1] += " bootstraps on locus";

	_nomFichier = DemandeFichier(
			_("Populations tree filename (Phylip format):"));

	try {
		if (_VcalcLocus.size() == 0)
			_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
					_square_distance, nbtirages, false);
		else
			_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
					_square_distance, nbtirages, false, &_VcalcLocus);
	} catch (Jeupop::Anomalie lepb) {
		cout
				<< _("Phylogenetic tree reconstruction aborted, tree file was not written")
				<< endl;
		return;
	}

	//	larbre.fElimineTrifurcation();
	ecritArbre(larbre, _nomFichier);
}

void ApplPopulations::ftreepopBootInd() {
	// calcul de distance entre toutes les populations
	// avec bootstrap sur les individus
	MatriceLD distances;
	int metdist;
	int metconstructarbre;

	ArbrePlus larbre;
	int nbtirages;

	metdist = menu_metdistpop();
	if (_choix == -1) {
		_choix = 1;
		return;
	}

	metconstructarbre = menu_metconstructarbre();
	nbtirages = DemandeEntier(
			_("How many times do you want to perform bootstraps ?"), 1,
			30000);

	larbre._titre.resize(2);
	larbre._titre[0].assign(""); // individus, populations
	larbre._titre[1].assign(""); // m�thode de distance, nb bootstrap

	larbre._titre[0].AjEntier(_Pjeupop->get_nbpop());
	larbre._titre[0] += " populations";

	larbre._titre[1] += DistancesGnt::get_nom_methode(metdist);
	larbre._titre[1] += ", ";
	larbre._titre[1].AjEntier(nbtirages);
	larbre._titre[1] += " bootstraps on individuals";

	_nomFichier = DemandeFichier(
			_("Populations tree filename (Phylip format):"));

	try {
		if (_VcalcLocus.size() == 0)
			_Pjeupop->f_BootstrapIndividus(larbre, metconstructarbre, metdist,
					_square_distance, nbtirages);
		else
			_Pjeupop->f_BootstrapIndividus(larbre, metconstructarbre, metdist,
					_square_distance, nbtirages, &_VcalcLocus);
	} catch (Jeupop::Anomalie lepb) {
		cout
				<< _("Phylogenetic tree reconstruction aborted, tree file was not written")
				<< endl;
		return;
	}

	//	larbre.fElimineTrifurcation();
	ecritArbre(larbre, _nomFichier);
}

void ApplPopulations::ecritGenepop() {
	//	cout << _("Output file name (Genepop modified format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(
			_("Output file name (Genepop modified format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		_Pjeupop->oGenepop(_sortie);
		_sortie.close();
	} catch (Jeupop::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		case 1:
			cerr << endl
					<< _("Genepop format allows only diploid genetic datasets")
					<< endl;
			break;
		case 2:
			//la numerotation est a refaire, avec une table de conversion
			//cerr << "ApplPop::ecritGenepop() impossible" << endl;
			Jeupop traduction(*_Pjeupop);

			_sortie.open("correspondances.txt", ios::out);
			traduction.f_trad2Gpop(_sortie);
			//			_sortie << ends;
			_sortie.close();

			_sortie.open(_nomFichier.c_str(), ios::out);
			traduction.oGenepopCano(_sortie);
			_sortie.close();

			break;
		}
	}
}

void ApplPopulations::ecritGenepopCano() {
	//	cout << _("Output file name (canonical Genepop format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(
			_("Output file name (canonical Genepop format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		_Pjeupop->oGenepopCano(_sortie);
		_sortie.close();
	} catch (Jeupop::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		case 1:
			cerr << endl
					<<_("Genepop format allows only diploid genetic datasets")
					<< endl;
			break;
		case 2:
			//la numerotation est a refaire, avec une table de conversion
			Jeupop traduction(*_Pjeupop);

			_sortie.open("correspondances.txt", ios::out);
			traduction.f_trad2Gpop(_sortie);
			//			_sortie << ends;
			_sortie.close();

			_sortie.open(_nomFichier.c_str(), ios::out);
			traduction.oGenepop(_sortie);
			_sortie.close();

			break;
		}
	}
}

void ApplPopulations::ecritPopulations() {
	//	cout << _("Output file name (Populations format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(_("Output file name (Populations format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		_Pjeupop->oPopulations(_sortie);
		_sortie.close();
	} catch (Jeupop::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		default:
			cerr << _("Error writing Populations file...") << endl;
		}
	}
}

void ApplPopulations::menu_formats() {

	Vecteur<unsigned int> Vlocus;
	Jeupop * Pjeupopsvg(0);

	int choix(1);
	while (choix != 0) {
		cout << endl << endl;
		cout << _("Output format:") << endl;
		cout << "0) " << _("Back") << endl;
		cout << "1) " << _("Choose locus to export (default: all)") << endl;
		cout << "2) " << _("Populations format") << endl;
		cout << "3) " << _("Populations XML format") << endl;
		cout << "4) " << _("Genepop format") << endl;
		cout << "5) " << _("Genepop modified format") << endl;
		cout << "6) " << _("Immanc format") << endl;
		cout << "7) " << _("microsat individuals format") << endl;
		cout << "8) " << _("microsat populations + frequencies format") << endl;
		cout << "9) " << _("LEA Likelihood Estimation of Admixture") << endl;
		cout << "10) " << _("Admix (G. Bertorelle)") << endl;
		cout << "11) " << _("Genetix") << endl;
		cout << "12) " << _("Fstat (Jerome Goudet)") << endl;

		choix = DemandeChoix(0, 12);

		switch (choix) {
		case 0:
			if (Pjeupopsvg != 0) {
				delete _Pjeupop;
				_Pjeupop = Pjeupopsvg;
			}
			break;
		case 1:
			//choix des locus
			Vlocus = menu_choixlocus();
			if (Vlocus.size() != 0) {
				Pjeupopsvg = _Pjeupop;
				_Pjeupop = new Jeupop(*Pjeupopsvg);
				_Pjeupop->GarderVlocus(Vlocus);
			}
			break;
		case 2:
			ecritPopulations();
			break;
		case 3:
			ecritPopulationsXML();
			break;
		case 4:
			ecritGenepopCano();
			break;
		case 5:
			ecritGenepop();
			break;
		case 6:
			ecritImmanc();
			break;
		case 7:
			ecritMsat(1);
			break;
		case 8:
			ecritMsat(2);
			break;
		case 9:
			ecritLea();
			break;
		case 10:
			ecritAdmix();
			break;
		case 11:
			ecritGenetix();
			break;
		case 12:
			ecritFstat();
			break;
		}
	}

}

void ApplPopulations::menu_popstructurees() {

	int choix(0);
	_choix = 1;
	while (_choix > 0) {
		cout << endl << endl;
		cout << _("Structured Populations") << endl;
		cout << endl << endl;
		cout << "0) " << _("back") << endl;
		cout << "1) " << _("Show structure level") << endl;
		cout << "2) " << _("Set level") << endl;
		cout << "3) " << _("Display Wright indices per loci") << endl;

		choix = DemandeChoix(0, 3);

		switch (choix) {
		case 0:
			_choix = -1;
			return;
			break;
		case 1:
			AffNiveauxPopStruc(cout);
			break;
		case 2:
			fsetniveau();
		case 3:
			Fstat lesfstats(_Pjeupop->get_Pracinepop());
			lesfstats.f_affparlocus(cout);
			break;
		}
	}
}

void ApplPopulations::menu_calculs() {

	int choix(0);
	_choix = 1;
	while (_choix > 0) {
		cout << endl << endl;
		cout << _("Allelic frequencies, Fstats") << endl;
		cout << endl << endl;
		cout << "0) " << _("back") << endl;
		cout << "1) " << _("Allelic diversity for reduced sample") << endl;
		cout << "2) " << _("Fst, Fis, Fit per populations") << endl;

		choix = DemandeChoix(0, 3);

		switch (choix) {
		case 0:
			_choix = -1;
			return;
			break;
		case 1:
			cout << endl << endl;
			cout << _("Compute allelic diversity") << endl;
			cout << _(" for reduced sample") << endl;
			frarefaction();
			break;
		case 2:
			ecritRapportFst();
			break;
		}
	}
}

void ApplPopulations::menu_arbrepop() {

	int choix(0);

	set_groupes_populations();

	_choix = 1;
	while (_choix > 0) {
		cout << endl << endl;
		cout << _("Reconstructing phylogenetic trees with populations") << endl;
		cout << endl << endl;
		cout << "0) " << _("back") << endl;
		cout << "1) " << _("Get distance matrix between populations") << endl;
		cout << "2) " << _("Phylogenetic tree of populations") << endl;
		cout << "3) "
				<< _("Phylogenetic tree of populations with bootstraps on locus")
				<< endl;
		cout << "4) "
				<< _("Phylogenetic tree of populations with bootstraps on individuals")
				<< endl;
		cout << "5) " << _("Choose locus to compute distances (default: all)")
				<< endl;

		choix = DemandeChoix(0, 5);

		switch (choix) {
		case 0:
			_choix = -1;
			return;
			break;
		case 1:
			fdistpop();
			break;
		case 2:
			ftreepop();
			break;
		case 3:
			ftreepopBootLocus();
			break;
		case 4:
			ftreepopBootInd();
			break;
		case 5:
			_VcalcLocus = menu_choixlocus();
			affVlocus(_VcalcLocus);
			break;
		}
	}
	reset_groupes();
}

void ApplPopulations::menu_arbreind() {

	int choix(0);

	set_groupes_individus();

	_choix = 1;
	while (_choix > 0) {
		cout << endl << endl;
		cout << _("Reconstructing phylogenetic trees with individuals") << endl;
		cout << endl << endl;
		cout << "0) " << _("back") << endl;
		cout << "1) " << _("Get distance matrix between individuals") << endl;
		cout << "2) " << _("Phylogenetic tree of individuals") << endl;
		cout << "3) "
				<< _("Phylogenetic tree of individuals with bootstraps on locus")
				<< endl;
		cout << "4) " << _("Choose locus to compute distances (default: all)")
				<< endl;

		choix = DemandeChoix(0, 4);

		switch (choix) {
		case 0:
			_choix = -1;
			return;
			break;
		case 1:
			fdistind();
			break;
		case 2:
			ftreeind();
			break;
		case 3:
			ftreeindBootLocus();
			break;
		case 4:
			_VcalcLocus = menu_choixlocus();
			affVlocus(_VcalcLocus);
			break;
		}
	}

	reset_groupes();
}

void ApplPopulations::AffNiveauxPopStruc(ostream &) {

	//Affichage des niveaux de structuration des populations
	Titre nom_niveaux;
	unsigned long i;

	_Pjeupop->get_nomniveauxstruc(nom_niveaux);

	cout << endl << endl;
	cout << _("Structured Population") << endl;
	cout << endl;

	for (i = 0; i < nom_niveaux.size(); i++) {
		cout << _("Level ") << i << ":" << endl;
		cout << nom_niveaux[i] << endl;
	}

}

void ApplPopulations::ecritImmanc() {
	//	cout << _("Output file format (Immanc format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(_("Output file format (Immanc format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		_Pjeupop->oImmanc(_sortie);
		_sortie.close();
	} catch (Jeupop::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		case 1:
			cerr << endl
					<< _("Immanc format allows only diploid genetic datasets")
					<< endl;
			break;
		case 2:
			//la numerotation est a refaire, avec une table de conversion
			Jeupop traduction(*_Pjeupop);

			_sortie.open("correspondances.txt", ios::out);
			traduction.f_trad2Gpop(_sortie);
			_sortie << ends;
			_sortie.close();

			_sortie.open(_nomFichier.c_str(), ios::out);
			traduction.oImmanc(_sortie);
			_sortie.close();

			break;
		}
	}
}

void ApplPopulations::ecritLea() {
	//		format LEA Likelihood Estimation of Admixture
	unsigned long P1, P2, H;

	P1
			= DemandePopulation(
					_("What is the name of the population P1 (parental population) ?"));
	P2
			= DemandePopulation(
					_("What is the name of the population P2 (parental population) ?"));
	H
			= DemandePopulation(
					_("What is the name of the population H (hybrid population)?"));

	//	cout << _("Output file name (LEA format, M.A. Beaumont, L. Chikhi) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier
			= DemandeFichier(
					_("Output file name (LEA format, M.A. Beaumont, L. Chikhi) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);

		JeuPopExp exportation(_Pjeupop);

		exportation.oLea(P1, P2, H, _sortie, cout);

		_sortie.close();
	} catch (JeuPopExp::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		case 1:
			break;
		case 2:
			break;
		default:
			cerr << _("Error number: ") << pb.le_pb << _(" in the object: ")
					<< "JeuPopExp" << endl;
			break;
		}
	}
}

void ApplPopulations::ecritAdmix() {
	//		format Admix http://www.unife.it/genetica/Giorgio/giorgio.html
	unsigned long P1, P2, H;
	string fichier_mtx;

	P1
			= DemandePopulation(
					_("What is the name of the population P1 (parental population) ?"));
	P2
			= DemandePopulation(
					_("What is the name of the population P2 (parental population) ?"));
	H
			= DemandePopulation(
					_("What is the name of the population H (hybrid population)?"));

	cout << _("Output file name (Admix .dat format, G. Bertorelle) ?") << endl;
	cin >> _nomFichier;

	cout << _("Output file name (Admix .mtx format, G. Bertorelle) ?") << endl;
	cin >> fichier_mtx;

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		JeuPopExp exportation(_Pjeupop);
		exportation.oAdmix_dat(P1, P2, H, _sortie, cout);
		_sortie.close();

		_sortie.open(fichier_mtx.c_str(), ios::out);
		exportation.oAdmix_mtx(_sortie, cout);
		_sortie.close();
	} catch (JeuPopExp::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		case 1:
			break;
		case 2:
			break;
		default:
			cerr << _("Error number: ") << pb.le_pb << _(" in the object: ")
					<< "JeuPopExp" << endl;
			break;
		}
	}
}

void ApplPopulations::ecritMsat(int choix) {
	//	cout << _("Output file (Microsat format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(_("Output file (Microsat format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		switch (choix) {
		case 1:
			_Pjeupop->oMsat(_sortie);
			break;
		default:
			_Pjeupop->oMsatFreq(_sortie);
			break;
		}
		_sortie.close();
	} catch (Jeupop::Anomalie pb) {
		_sortie.close();
		switch (pb.le_pb) {
		//		case 1:
		//			cerr << endl << "le format Immanc ne permet que le stockage de pop diploides" << endl;
		//			break;
		case 2:
			//les noms d'alleles ne sont pas des tailles de msat
			cout << _("Populations is not able to export dataset:") << endl;
			//			cout << _("Les noms d'alleles doivent correspondre a des tailles de microsatellites (ou au nombre de repetitions).") << endl;
			cout
					<< _("Alleles names should be numeric, corresponding to allele size (or number of repetition).")
					<< endl;

			break;
		}
	}
}

int ApplPopulations::menu_metconstructarbre() {

	int choix;
	_choix = 0;

	//	while (_choix != 0) {
	cout << endl << endl;
	//		cout << "0) Menu principal" << endl;
	cout << "1) " << _("UPGMA") << endl;
	cout << "2) " << _("Neighbor Joining") << endl;
	cout << endl << _("Your choice: ");
	cin >> choix;

	switch (choix) {
	//		case 0:
	//			_choix = -1;
	//			return;
	//			break;
	case 1:
		return (1);
		break;
	case 2:
		return (2);
		break;
	default:
		return (2);
		break;
	}
	//	}

}

int ApplPopulations::menu_metdistpop() {

	int choix;
	unsigned int i, nb_methods(DistancesGnt::get_nb_methodes());
	_choix = 0;

	//	while (_choix != 0) {
	cout << endl << _("Distance methods") << endl;
	cout << "0) " << _("Back") << endl;
	for (i = 1; i < nb_methods; i++) {
		cout << (i) << ") " << DistancesGnt::get_nom_methode(i) << endl;
	}
	if (_square_distance)
		cout << nb_methods << ") " << _("Squared distance: yes") << endl;
	else
		cout << nb_methods << ") " << _("Squared distance: no") << endl;
	/*
	 cout << "1) " << _("DAS, Allelic Shared Distance (Chakraborty et Jin., 1993)") << endl;
	 cout << "2) " << _("Nei, minimum genetic distance, Dm (Nei,1987)") << endl;
	 cout << "3) " << _("Nei, standard genetic distance, Ds (Nei, 1987)") << endl;
	 cout << "4) " << _("Cavalli-Sforza and Edwards, Dc (1967)") << endl;
	 cout << "5) " << _("Nei et al's, Da (1983)") << endl;
	 cout << "6) " << _("Goldstein et al., dmu2 (1995a)") << endl;
	 cout << "7) " << _("Latter, Fst (1972)") << endl;
	 cout << "8) " << _("Prevosti et al.'s, Cp (1975)") << endl;
	 cout << "9) " << _("Rogers', Dr (1972)") << endl;
	 cout << "10) " << _("Average Square Distance (ASD, Goldstein, Slatkin 1995)") << endl;
	 cout << "11) " << _("Shriver et al's, Dsw (1995)") << endl;
	 cout << "12) " << _("Lev A. Zhivotovsky, DR (1999)") << endl;
	 */

	choix = DemandeChoix(0, nb_methods + 1);

	switch (choix) {
	case 0:
		_choix = -1;
		return (-1);
		break;
	case 1:
		return (101); //Das sur les individus
		break;
	case 2:
		return (102); //Nei sur les populations
		break;
	case 3:
		return (103); //Nei sur les populations
		break;
	case 4:
		return (104); //Cavalli-Sforza and Edwards' (1967)sur les populations
		break;
	case 5:
		return (5); // Nei et al's, Da (1983) sur les populations
		break;
	case 6:
		return (106); // Goldstein et al., Mu (1995a) sur les populations
		break;
	case 7:
		return (107); // Latter's Fst (1972) sur les populations
		break;
	case 8:
		return (108); // Prevosti et al.'s, Cp (1975) sur les populations
		break;
	case 9:
		return (109); // Rogers', Dr (1972) sur les populations
		break;
	case 10:
		return (110); // Goldstein et al. (1995b) Slatkin 1995
		break;
	case 11:
		return (111); // Shriver et al's, Dsw (1995)
		break;
	case 12:
		return (112); // Lev A. Zhivotovsky, DR (1999)
		break;
	case 13:
		return (113); // Reynolds unweighted (1983)
		break;
	case 14:
		return (114); // Reynolds weighted (1983)
		break;
	case 15:
		return (115); // Reynolds least squares (1983)
		break;

	case 16:
		_square_distance = !_square_distance;
		return (menu_metdistpop());
		break;

	default:
		return (5);
		break;
	}
}

void ApplPopulations::fconstructarbre(MatriceLD &distances,
		string & nomficarbre, int methodearbre) {
	ArbrePlus larbre;
	bool continuer(true);

	if (_temp.size() != 0)
		larbre._titre = _temp;
	switch (methodearbre) {
	case 1:
		cerr << _("Building phylogenetic tree with UPGMA...") << endl;
		larbre._titre.push_back("UPGMA");
		break;
	case 2:
		cerr << _("Building phylogenetic tree with Neighbor-Joining...")
				<< endl;
		larbre._titre.push_back("Neighbor-Joining");
		break;
	case 101:
		cerr << _("Building phylogenetic tree with UPGMA...") << endl;
		larbre._titre.push_back("UPGMA");
		break;
	case 102:
		cerr << _("Building phylogenetic tree with Neighbor-Joining...")
				<< endl;
		larbre._titre.push_back("Neighbor-Joining");
		break;
	default:
		cerr
				<< _("Error missing construction method to build phylogenetic tree")
				<< endl;
		//		larbre._titre.push_back("UPGMA");
		return;
	}

	while (continuer) {
		continuer = false;
		try {
			//		_sortie.open("debug.txt", ios::out);
			//		distances.oExcel(_sortie);
			//		_sortie.close();
			//cerr << "ApplPopulations::fconstructarbre debut iDistances" << endl;
			larbre.iDistances(distances, methodearbre);
			//			larbre.fElimineTrifurcation();
			//cerr << "ApplPopulations::fconstructarbre fin iDistances" << endl;

			ecritArbre(larbre, nomficarbre);
		} catch (Arbre::Anomalie pb) {
			switch (pb.le_pb) {
			case 4:
				cout << _("Inconsistant matrix file format") << endl;
				break;
			case 5:
				cout << _("the matrix is too small") << endl;
				break;
			case 6:
				cout << _("Negative distances in the matrix...") << endl;
				cout << _("the smallest value is: ")
						<< distances.get_ppvaleur() << endl;
				cout
						<< _("to build a tree, you must set negative values to zero.")
						<< endl;
				if (DemandeOuiNon(
						_("Do you want to set negative values to zero (Y/N) ?"))) {
					distances.f_neg2zero();
					continuer = true;
				}
				break;
			}
			if (continuer == false)
				cout << _("The tree file was not written.") << endl;

		}
	}// continuer
	_temp.resize(0);
}

void ApplPopulations::ecritArbre(ArbrePlus & larbre, string nomFichier) {
	//cerr << "ApplPopulations::ecritArbre(ArbrePlus & larbre, string nomFichier) debut" << endl;
	set_groupes_arbre(larbre);

	if (nomFichier == "") {
		cout << _("Output tree file:") << endl;
		nomFichier = DemandeFichier(
				_("Name of output file (Phylip tree file) ?"));
	}

	_sortie.open(nomFichier.c_str(), ios::out);
	larbre.oFichier(_sortie, 1);
	//	_sortie << larbre;
	//	_sortie << endl << ends;
	_sortie.close();
	//cerr << "ApplPopulations::ecritArbre(ArbrePlus & larbre, string nomFichier) fin" << endl;
}

void ApplPopulations::fLigneCommande(char ** commandes, int nbcommandes) {
	Titre tab_commandes(commandes, nbcommandes);

	if (tab_commandes.Position("-phylogeny") > 0)
		fLiPhylogeny(tab_commandes);
	else if (tab_commandes.Position("--test") >= 0)
		fLiTest(tab_commandes);
	else
		fLiHelp();
}

void ApplPopulations::fLiPhylogeny(Titre & tab_commandes) {
	// demande d'arbre phylog�n�tique
	int pos;
	//	unsigned int niveau(100); //niveau pour populations structur�es
	ArbrePlus larbre;

	istream * Pentree(&cin);
	ostream * Psortie(&cout);

	tab_commandes.Suppr(0);

	//fichiers d'entree ou entree standard (par d�faut)
	_fichier.open(tab_commandes[0].c_str(), ios::in);

	if (_fichier.is_open())
		Pentree = &_fichier;
	try {
		_Pjeupop = new Jeupop();
		*Pentree >> *(_Pjeupop);
		_fichier.close();
		_fichier.clear();
	} catch (Jeupop::Anomalie pb) {
		_fichier.close();
		_fichier.clear();
		delete _Pjeupop;

		switch (pb.le_pb) {
		case 4:
			cerr << _("Input file format seems incorrect...") << endl;
			return;
			break;
		}
	}

	//fichiers de sortie ou sortie standard (sortie standard par d�faut)
	pos = tab_commandes.Position("-output");
	if ((pos > 0) && (pos + 1 != (long) tab_commandes.size())) {
		_sortie.open(tab_commandes[pos + 1].c_str(), ios::out);
		cerr
				<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) debug output : "
				<< tab_commandes[pos + 1].c_str() << endl;
		if (_sortie.is_open() != 0)
			Psortie = &_sortie;
		tab_commandes.Suppr(pos + 1);
		tab_commandes.Suppr(pos);
	}

	// Individus ou Populations ? (populations par d�faut)
	bool sur_pop(true);

	//tab_commandes.Suppr(tab_commandes.Position("-phylogeny"));
	pos = tab_commandes.Position("-phylogeny");

	if ((pos + 1 != (long) tab_commandes.size()) && (tab_commandes[pos + 1]
			== "ind")) {
		sur_pop = false;
		tab_commandes.Suppr(pos + 1);
		cerr
				<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) debug phylogeny : ind"
				<< endl;
	} else if ((pos + 1 != (long) tab_commandes.size()) && (tab_commandes[pos
			+ 1] == "pop")) {
		tab_commandes.Suppr(pos + 1);
		cerr
				<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) debug phylogeny : pop"
				<< endl;
	}
	tab_commandes.Suppr(pos);

	// Methode de distance ? (Nei standard par d�faut)
	int metdist(102);
	pos = tab_commandes.Position("-dist");
	if ((pos > 0) && (pos + 1 != (long) tab_commandes.size())) {
		if (tab_commandes[pos + 1] == "DAS") {
			metdist = 5;
			tab_commandes.Suppr(pos + 1);
		} else if (tab_commandes[pos + 1] == "Dm") {
			metdist = 101;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Ds") || (tab_commandes[pos + 1]
				== "nei")) {
			metdist = 102;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Dc") || (tab_commandes[pos + 1]
				== "cav")) {
			metdist = 103;
			tab_commandes.Suppr(pos + 1);
		} else if (tab_commandes[pos + 1] == "Da") {
			metdist = 104;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "dmu2")
				|| (tab_commandes[pos + 1] == "goldstein")) {
			metdist = 106;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Fst") || (tab_commandes[pos + 1]
				== "latter")) {
			metdist = 107;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Cp") || (tab_commandes[pos + 1]
				== "prevosti")) {
			metdist = 108;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Dr") || (tab_commandes[pos + 1]
				== "roger")) {
			metdist = 109;
			tab_commandes.Suppr(pos + 1);
		} else if (tab_commandes[pos + 1] == "ASD") {
			metdist = 110;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Dsw") || (tab_commandes[pos + 1]
				== "shriver")) {
			metdist = 111;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "DR") || (tab_commandes[pos + 1]
				== "zhiv")) {
			metdist = 112;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Dru") || (tab_commandes[pos + 1]
				== "reynoldsu")) {
			metdist = 113;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Drw") || (tab_commandes[pos + 1]
				== "reynoldsw")) {
			metdist = 114;
			tab_commandes.Suppr(pos + 1);
		} else if ((tab_commandes[pos + 1] == "Drl") || (tab_commandes[pos + 1]
				== "reynoldsl")) {
			metdist = 115;
			tab_commandes.Suppr(pos + 1);
		}
		/*			return(5); //Das sur les individus
		 return(101); //Nei sur les populations, Dm
		 return(102); //Nei sur les populations, Ds
		 return(103); //Cavalli-Sforza and Edwards' (1967), Dc
		 return(104); // Nei et al's, Da (1983)
		 return(106); // Goldstein et al., Mu (1995a), dmu2
		 return(107); // Latter's Fst (1972)
		 return(108); // Prevosti et al.'s, Cp (1975)
		 return(109); // Rogers', Dr (1972)
		 return(110); // Goldstein et al. (1995b) Slatkin 1995, ASD
		 return(111); // Shriver et al's, Dsw (1995)
		 return(112); // Lev A. Zhivotovsky, DR (1999)
		 */
		tab_commandes.Suppr(pos);
	}
	cerr
			<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) metdist : "
			<< metdist << endl;

	// Methode de construction d'arbre ? (Neigbhor Joining par d�faut)
	int metconstructarbre(2);
	pos = tab_commandes.Position("-construct");
	if ((pos > 0) && (pos + 1 != (long) tab_commandes.size())) {
		if (tab_commandes[pos + 1] == "upgma") {
			metconstructarbre = 1;
			tab_commandes.Suppr(pos + 1);
			tab_commandes.Suppr(pos);
		} else if (tab_commandes[pos + 1] == "nj") {
			metconstructarbre = 2;
			tab_commandes.Suppr(pos + 1);
			tab_commandes.Suppr(pos);
		}
	}
	cerr
			<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) metconstructarbre : "
			<< metconstructarbre << endl;

	//nombre d'it�rations pour le bootstrap
	int nb_iterations(0);

	// bootstrap locus ou bootstrap individus ? (bootstrap locus par d�faut)
	bool bootstrap_locus(true);

	if (sur_pop) {

		pos = tab_commandes.Position("-bootstrap_ind");
		if (pos > 0) {
			nb_iterations = 100;
			bootstrap_locus = false;
			if ((pos + 1 != (long) tab_commandes.size()) && (tab_commandes[pos
					+ 1].EstUnChiffre())) {
				nb_iterations = tab_commandes[pos + 1];
				tab_commandes.Suppr(pos + 1);
			}
			tab_commandes.Suppr(pos);
		}

		pos = tab_commandes.Position("-level");
		if (pos > 0) {
			_niveau = 100;
			if ((pos + 1 != (long) tab_commandes.size()) && (tab_commandes[pos
					+ 1].EstUnChiffre())) {
				_niveau = tab_commandes[pos + 1];
				tab_commandes.Suppr(pos + 1);
			}
			tab_commandes.Suppr(pos);
		}
	} else {
		pos = tab_commandes.Position("-bootstrap_ind");
		if (pos > 0) {
			cerr
					<< "ERROR: Populations is unable to bootstrap on individuals to make a phylogenetic tree of individuals"
					<< endl;
			return;
		}
	}

	pos = tab_commandes.Position("-bootstrap_locus");
	if (pos > 0) {
		nb_iterations = 100;
		if ((pos + 1 != (long) tab_commandes.size())
				&& (tab_commandes[pos + 1].EstUnChiffre())) {
			nb_iterations = tab_commandes[pos + 1];
			tab_commandes.Suppr(pos + 1);
		}
		tab_commandes.Suppr(pos);
	}
	cerr
			<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) bootstrap_locus : "
			<< bootstrap_locus << endl;
	cerr
			<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) nb_iterations : "
			<< nb_iterations << endl;

	//---------------------------------------------
	// Décryptage de la ligne de commande terminé
	// ----------------------------------------------

	if (sur_pop) {
		//phylogenie sur les populations
		set_groupes_populations();
		larbre._titre.resize(2);
		larbre._titre[0].assign(""); // individus, populations
		larbre._titre[1].assign(""); // méthode de distance, nb bootstrap

		larbre._titre[0].AjEntier(_Pjeupop->get_nbpop());
		larbre._titre[0] += " populations";

		larbre._titre[1] += DistancesGnt::get_nom_methode(metdist);

		if (nb_iterations == 0) {
			//pas de bootstrap
			// calcul de distance entre toutes les populations
			MatriceLD distances;

			try {
				_Pjeupop->f_distgntpop(distances, metdist, _niveau);
			} catch (Jeupop::Anomalie pb) {
				cerr
						<< "ApplPopulations::fLiPhylogeny(Titre & tab_commandes) ERROR: "
						<< pb.le_pb << endl;
				return;
			}
			try {
				larbre.iDistances(distances, metconstructarbre);
				//				larbre.fElimineTrifurcation();
			} catch (Arbre::Anomalie pb) {
				switch (pb.le_pb) {
				case 4:
					cout << _("Inconsistant matrix file format");
					break;
				case 5:
					cout << _("the matrix is too small");
					break;
				case 6:
					cout << _("Negative distances in the matrix");
					break;
				}
				return;
			}
		} else {
			larbre._titre[1] += ", ";
			larbre._titre[1].AjEntier(nb_iterations);

			if (bootstrap_locus) {
				larbre._titre[1] += " bootstraps on locus";
				_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
						_square_distance, nb_iterations, false);
			} else {
				larbre._titre[1] += " bootstraps on individuals";
				_Pjeupop->f_BootstrapIndividus(larbre, metconstructarbre,
						metdist, _square_distance, nb_iterations);
			}

			//			larbre.fElimineTrifurcation();
		}
	} else {
		//phylogenie sur les individus
		set_groupes_individus();
		larbre._titre.resize(2);
		larbre._titre[0].assign(""); // individus, populations
		larbre._titre[1].assign(""); // m�thode de distance, nb bootstrap

		larbre._titre[0].AjEntier(_Pjeupop->get_nbind());
		larbre._titre[0] += " individuals";

		cerr
				<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) phylogeny on individuals "
				<< endl;

		larbre._titre[1] += DistancesGnt::get_nom_methode(metdist);

		if (nb_iterations == 0) {
			//pas de bootstrap
			// calcul de distance entre tous les individus
			MatriceLD distances;

			try {

				cerr
						<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) Pjeupop->f_distgnt(distances, metdist, _square_distance); "
						<< endl;
				_Pjeupop->f_distgnt(distances, metdist, _square_distance);
			} catch (Jeupop::Anomalie pb) {
				cerr
						<< "ApplPopulations::fLiPhylogeny(Titre & tab_commandes) ERROR: "
						<< pb.le_pb << endl;
				return;
			}

			try {
				cerr
						<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) larbre.iDistances "
						<< endl;
				larbre.iDistances(distances, metconstructarbre);
				//				larbre.fElimineTrifurcation();
				cerr
						<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) end larbre.iDistances "
						<< endl;
			} catch (Arbre::Anomalie pb) {
				switch (pb.le_pb) {
				case 4:
					cout << _("Inconsistant matrix file format");
					break;
				case 5:
					cout << _("the matrix is too small");
					break;
				case 6:
					cout << _("Negative distances in the matrix");
				}
			}
			//return;
		} else {
			//bootstrap sur les locus
			larbre._titre[1] += ", ";
			larbre._titre[1].AjEntier(nb_iterations);
			larbre._titre[1] += " bootstraps on locus";
			_Pjeupop->f_BootstrapLocus(larbre, metconstructarbre, metdist,
					nb_iterations, true);

			//			larbre.fElimineTrifurcation();
		}
	}

	cerr
			<< "DEBUG ApplPopulations::fLiPhylogeny(Titre & tab_commandes) set_groupes_arbre(larbre); "
			<< endl;
	set_groupes_arbre(larbre);
	larbre.oFichier(*Psortie);
	reset_groupes();

	//	*Psortie << larbre;
	//	larbre.oFichier(*Psortie);

	if (_sortie.is_open() != 0)
		_sortie.close();

}

void ApplPopulations::fLiHelp() const {
	cout << _("Online help missing") << endl;
	cout << _("Please visit our website :") << endl;
	cout << "http://www.bioinformatics.org/~tryphon/populations/" << endl;
}

void ApplPopulations::fLiTest(Titre & tab_commandes) {
	cout << "test du jour" << endl;
	cout << "Copie d'objet Jeupop" << endl;

	istream * Pentree(&cin);
	//	ostream * Psortie(&cout);

	//	tab_commandes.Suppr(0);

	//fichiers d'entree ou entree standard (par d�faut)
	_fichier.open("toutc2.txt", ios::in);

	if (_fichier.is_open())
		Pentree = &_fichier;
	try {
		_Pjeupop = new Jeupop();
		*Pentree >> *(_Pjeupop);
		_fichier.close();
		_fichier.clear();
	} catch (Jeupop::Anomalie pb) {
		_fichier.close();
		_fichier.clear();
		delete _Pjeupop;

		switch (pb.le_pb) {
		case 4:
			cerr << "Erreur de lecture..." << endl;
			return;
			break;
		}
	}

	//	_Pjeupop->oGenepop(cout);
	Jeupop copie(*_Pjeupop);

	//	copie.oGenepopCano(cout);

}

void ApplPopulations::affPubEntree() const {

	cout << endl << endl;
	cout << "**********************************************************"
			<< endl;
	cout << "*     Populations " << version_populations
			<< "                                 *" << endl;
	cout << "*      langella@moulon.inra.fr                           *"
			<< endl;
	cout << "*     http://bioinformatics.org/project/?group_id=84     *"
			<< endl;
	cout << "**********************************************************"
			<< endl;
	cout << endl << endl;

	// cout << log (10) << endl; //log n�perien
}

/** Choix de locus */
Vecteur<unsigned int> ApplPopulations::menu_choixlocus() const {

	Vecteur<unsigned int> Vlocus;
	_Pjeupop->f_selectlocustous(Vlocus);
	signed int pos;

	int choix(1);
	while (choix > 0) {
		cout << endl << endl;
		cout << _("Locus selection:") << endl;
		cout << "0) " << _("back") << endl;
		cout << "1) " << _("Select all loci (default)") << endl;
		cout << "2) " << _("Remove all loci") << endl;
		cout << "3) " << _("Add a particular locus") << endl;
		cout << "4) " << _("Remove a particular locus") << endl;
		cout << "5) " << _("Display selected loci") << endl;

		choix = DemandeChoix(0, 5);

		switch (choix) {
		case 0:
			return (Vlocus);
			break;
		case 1: // ajouter tous les locus
			_Pjeupop->f_selectlocustous(Vlocus);
			break;
		case 2: //enlever tous les locus
			Vlocus.resize(0);
			break;
		case 3: //ajouter un locus
			pos = DemandeLocus();
			if (pos != -1)
				Vlocus.push_back((unsigned int) pos);
			break;
		case 4: //enlever un locus
			pos = DemandeLocus();
			if (pos != -1) {
				pos = Vlocus.Position((unsigned int) pos);
				if (pos >= 0)
					Vlocus.Suppr(pos);
			}
			break;
		case 5: //affichage des locus selectionnes
			affVlocus(Vlocus);
			break;
		}
	}
	return (Vlocus);
}
/**  */
void ApplPopulations::affVlocus(const Vecteur<unsigned int> & Vlocus) const {
	unsigned int i;

	cout << endl;
	for (i = 0; i < Vlocus.size(); i++)
		cout << _Pjeupop->get_nomlocus(Vlocus[i]) << " ";
	cout << endl;
}
/** Demande le nom ou le numero d'un locus */
int ApplPopulations::DemandeLocus(const char laquestion[]) const {
	// float Application::DemandeReel(char laquestion[], float inf, float sup) const{
	biolib::vecteurs::ChaineCar rep;
	int nblocus(_Pjeupop->get_nbloc());
	int numlocus(-1);

	if (laquestion == 0)
		cout << _("Name or number of the locus: ") << endl;
	else
		cout << laquestion << endl;
	cin >> rep;

	numlocus = _Pjeupop->get_numloc(rep);
	if (numlocus == -1) {
		numlocus = rep;
		numlocus--;
	}

	if ((numlocus < 0) || (numlocus >= nblocus)) {
		cerr << _("The locus ") << rep << _(" was not found") << endl;
		numlocus = -1;
	}
	return (numlocus);
}

void ApplPopulations::ecritGenetix() {
	_nomFichier = DemandeFichier(_("Output file name (Genetix format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		JeuPopExp jeuaexporter(_Pjeupop);

		jeuaexporter.oGenetix(_sortie, cerr);

		_sortie.close();
	} catch (JeuPopExp::Anomalie pb) {
		_sortie.close();
		cerr << pb.fmessage(pb.le_pb) << endl;
	}
}

void ApplPopulations::ecritFstat() {
	_nomFichier = DemandeFichier(_("Output file name (Fstat format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		JeuPopExp jeuaexporter(_Pjeupop);

		jeuaexporter.oFstat(_sortie, cerr);

		_sortie.close();
	} catch (JeuPopExp::Anomalie pb) {
		_sortie.close();
		cerr << pb.fmessage(pb.le_pb) << endl;
	}
}

void ApplPopulations::ecritRapportFst() {
	cout << endl;
	cout << _("Fst, Fis and Fit computation") << endl;
	cout << "" << endl;
	JeuMatriceLD mat_resultat;
	_nomFichier = DemandeFichier(_("Output file name ?"));

	cout << endl;
	cout << _("computing...") << endl;
	cout << "" << endl;
	Fstat lesfstats(_Pjeupop->get_Pracinepop());
	//	lesfstats.f_affparlocus(cout);
	lesfstats.f_calcFstFisFit(mat_resultat);

	ecritJeuMatriceLD(mat_resultat, _nomFichier);

}

void ApplPopulations::fmicrosatcorrections() {
#ifdef XMLREADMICROSATCORRECTION_H
	while (_fichier.is_open() == 0) {
		cout << _("Name of the XML file containing corrections ?") << endl;
		cin >> _nomFichier;

		_fichier.open(_nomFichier.c_str(), ios::in);
		_fichier.clear();
	}

	try {
		XMLreadMicrosatCorrection parser(*_Pjeupop);
		parser.iParseFlux(_fichier);
		_fichier.close();
	}
	catch (XMLreadMicrosatCorrection::Anomalie pb) {
		_fichier.close();
		//throw Anomalie(1);
	}

#else
	cout << endl;
	cout << _("Sorry this version of Populations is unable to read XML files.")
			<< endl;
	cout << _("Try the linux version.") << endl;
	cout << "" << endl;
#endif  
}

void ApplPopulations::ecritPopulationsXML() {
	//	cout << _("Output file name (Populations format) ?") << endl;
	//	cin >> _nomFichier;
	_nomFichier = DemandeFichier(
			_("Output file name (XML Populations format) ?"));

	try {
		_sortie.open(_nomFichier.c_str(), ios::out);
		JeuPopExp jeuaexporter(_Pjeupop);

		jeuaexporter.oPopulationsXML(_sortie, cerr);

		_sortie.close();
	} catch (JeuPopExp::Anomalie pb) {
		_sortie.close();
		cerr << pb.fmessage(pb.le_pb) << endl;
	}
}
