
/***************************************************************************
                          strucpop.h  -  Librairie d'objets permettant de manipuler des données
                          						spécifiques aux StrucPops
                             -------------------
    begin                : ven sep 01 10:25:55 CEST 2000
    copyright            : (C) 2000 by Olivier Langella CNRS UPR9034
    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.                                   *
 *                                                                         *
 ***************************************************************************/


#ifndef STRUCPOP_H
#define STRUCPOP_H


//#include"arbres.h"
#include "vecteurs.h"
#include "individu.h"

//typedef biolib::vecteurs::ChaineCar ChaineCar;

class Jeupop;
class MetaPop;


class StrucPop { //StrucPops structurée
public :
	StrucPop(Jeupop * pdonnees);
//constructeur de copies
	StrucPop(const StrucPop & popori, MetaPop * Pmetapop, Jeupop * Pjeu);
	//allocation et désallocation
//	StrucPop(int nbind = 0);
//	StrucPop(Jeupop * pdonnees, long nbind);
//	StrucPop(Jeupop * pdonnees, const StrucPop & popori);
//	StrucPop(const StrucPop &);
	virtual ~StrucPop();

	virtual bool DuType(const string &) const {return(false);};

	virtual void AjouterIndividu(Individu * Pind) {};
//	virtual void AjouterPopulation(StrucPop * Pstrucpop) {};
	virtual void AjouterPopulation(MetaPop * ) {};
	virtual void AjouterPopulation(Population * ) {};

	void AjouterAllIntrogressant(Allele * Pall);
	//génétique

	//**** fonctions de base
	Allele* get_Pall(unsigned long ind,unsigned long all) const;
	Allele* get_Pall(unsigned long ind, unsigned long locus, unsigned int numall) const;
	Allele * get_Pall(const string & nomlocus, const string & nomall) const;
	//nombre d'individus
	unsigned long get_nbind() const {return(_tabPind.size());};
//	long get_nbloc() const {return(_nbloc = _Pjeu->get_nbloc());}; 
	unsigned long get_nbloc() const {return(_nbloc);};
//	unsigned long get_nballloc(unsigned long i) const {return(_Pjeu->get_Plocus(i)->get_nball());};
	unsigned int get_nploidie() const {return(_nploidie);};
	virtual Individu* get_Pind(unsigned long i) const {return(_tabPind[i]);};
	inline Jeupop* get_Pjeu() const;
	//nom de la StrucPop
	//const char * get_nom() {return(_nom.c_str());};
	const string & get_nom() const {return(_nom);};
	const string & get_couleur() const {return(_couleur);};
	const string & get_nomind(long nbind) const;
	virtual void get_nomniveauxstruc(Titre & nom_niveaux) const {};
	virtual unsigned int get_niveau() const {return(0);};
	virtual unsigned long get_nbpop() const {return(0);};
	virtual MetaPop* get_Pmetapop() const {return(_Pmetapop);};
	virtual const string & get_idXML() const {return(_idXML);};

	virtual void set_nploidie() {};
	virtual void set_nom(const string & nom);

	//nombres d'allèles pour un locus
	void r_alldiff(int, Vecteur<Allele*>&) const; //num locus, tableau sur les Alleles differents de ce locus
	//nombres de copies d'un allèle d'un locus
	//pointeur sur allèle
//	Allele* r_Pall(int, int) const; //num locus, num allèle
	inline unsigned long r_nbcopall(Allele *) const; //num locus, num allèle
	inline unsigned long r_nbcopallBootInd(Allele *) const; //num locus, num allèle
	inline unsigned long r_nballnonnuls(unsigned long locus) const; //nombre d'alleles non nuls pour un locus
	unsigned long r_nballnonnulsBootInd(unsigned long locus) const;

	long double f_heterozygotieatt(unsigned long locus, unsigned long * Pnbpopcalc) const; //Hs
	long double f_heterozygotieobs(unsigned long locus, unsigned long * Pnbpopcalc) const;
	long double f_calcfreq(Allele * Pall) const;
	long f_calcfreqabsolue(Allele * Pall) const;

	//**** fonctions évoluées
	//raréfaction de l'effectif d'une StrucPop
	double r_rare(unsigned long, unsigned int) const; //nouvel effectif, num locus


	virtual void f_rempliTabStrucPop(Vecteur<StrucPop*> &, unsigned int) {};
	//const StrucPop& operator= (const StrucPop &);
  /** Suppression de la population */
  virtual void SupprPop(StrucPop * Ppop) {};

  /** réaffectation du nombre de locus */
  virtual void set_nbloc();

  virtual void oPopulationsXML(unsigned int id, ostream & sortie, ostream & infos) {};

  
	friend class DistancesGnt;
	friend class Jeupop;
	friend class Individu;

protected :
	virtual void set_idXML(const string & id) {_idXML=id;};
//	void sort_all();//tri de _tabPall par loci
	void resize_loc();
	virtual void reset();

	void f_bootstrap(); //bootstrap sur les individus

	virtual void ifAjouterIndividu(const Individu * Pind);

  /** Supprime l'individu Pind du tableau */
  void SupprtabIndividu(Individu * Pind);

	unsigned int _nploidie;
//	string _nom;
	string _nom;
	Jeupop * _Pjeu;
	MetaPop * _Pmetapop;
	
	unsigned long _nbind; //nb d'individus dans cette pop
	
	vector<Individu*> _tabPind;
	unsigned long _nbloc; //nb de loci
//	vector<Allele*> _tabPall;

	Vecteur<Allele*> _tabAllIntrogressant;

	vector<Individu*> _VcalcInd;

	string _couleur;

  string _idXML;


public:

	struct Anomalie{
		// 1-> acces hors borne dans alleles
		// 2-> copie impossible: nploidie differents
		// 3-> copie impossible: nbloc differents
		// 5-> copie impossible: nom d'allele non present dans le jeu de donnees
		// 6-> copie impossible: nom de locus non present dans le jeu de donnees
		// 7-> acces hors borne dans les locus
		int le_pb;
		Anomalie (int i):le_pb(i){};
	};

};



unsigned long StrucPop::r_nbcopallBootInd(Allele * Pall) const {
	// retourne le nb de copies d'un allèle pour un locus
	// specifique aux calculs avec bootstrap sur individus
	unsigned long resultat(0);
	unsigned long nbind(_VcalcInd.size());
	unsigned long i;
	
	for (i=0;i < nbind;i++) {
//		resultat += _VcalcInd[i]->_tabPall.getNbOccurence(Pall);
		resultat += _VcalcInd[i]->r_nbcopall(Pall);
	}

	return(resultat);
}

inline unsigned long StrucPop::r_nbcopall(Allele * Pall) const {
	// retourne le nb de copies d'un allèle pour un locus
	unsigned long resultat(0);
	unsigned long nbind(_tabPind.size());
	unsigned long i;
	
	for (i=0;i < nbind;i++) {
		resultat += _tabPind[i]->_tabPall.getNbOccurence(Pall);
//		resultat += _tabPind[i]->r_nbcopall(Pall);
	}

	return(resultat);
}


inline unsigned long StrucPop::r_nballnonnuls(unsigned long locus) const {
	// retourne le nb de copies d'allèles non nuls pour un locus
	unsigned long resultat(0);
	unsigned long nbind(_tabPind.size());
	unsigned long nploidie(get_nploidie());
	unsigned long i, j;
	
	for (i=0;i < nbind;i++) {
		for (j=0;j < nploidie;j++) {
			if (_tabPind[i]->_tabPall[(locus * nploidie) + j]->_miss) continue;
			resultat++;
		}
	}

	return(resultat);
}


inline Jeupop* StrucPop::get_Pjeu() const {
	return(_Pjeu);
}

#endif

