.. _`chapter:popgen`:

Bio.PopGen: Population genetics
===============================

``Bio.PopGen`` is a Biopython module supporting population genetics,
available in Biopython 1.44 onwards. The objective for the module is to
support widely used data formats, applications and databases.

GenePop
-------

GenePop (http://genepop.curtin.edu.au/) is a popular population genetics
software package supporting Hardy-Weinberg tests, linkage
disequilibrium, population differentiation, basic statistics,
:math:`F_{st}` and migration estimates, among others. GenePop does not
supply sequence based statistics as it doesn’t handle sequence data. The
GenePop file format is supported by a wide range of other population
genetic software applications, thus making it a relevant format in the
population genetics field.

``Bio.PopGen`` provides a parser and generator of GenePop file format.
Utilities to manipulate the content of a record are also provided. Here
is an example on how to read a GenePop file (you can find example
GenePop data files in the Test/PopGen directory of Biopython):

.. code:: python

   from Bio.PopGen import GenePop

   with open("example.gen") as handle:
       rec = GenePop.read(handle)

This will read a file called example.gen and parse it. If you do print
rec, the record will be output again, in GenePop format.

The most important information in rec will be the loci names and
population information (but there is more – use help(GenePop.Record) to
check the API documentation). Loci names can be found on rec.loci_list.
Population information can be found on rec.populations. Populations is a
list with one element per population. Each element is itself a list of
individuals, each individual is a pair composed by individual name and a
list of alleles (2 per marker), here is an example for rec.populations:

.. code:: python

   [
       [
           ("Ind1", [(1, 2), (3, 3), (200, 201)]),
           ("Ind2", [(2, None), (3, 3), (None, None)]),
       ],
       [
           ("Other1", [(1, 1), (4, 3), (200, 200)]),
       ],
   ]

So we have two populations, the first with two individuals, the second
with only one. The first individual of the first population is called
Ind1, allelic information for each of the 3 loci follows. Please note
that for any locus, information might be missing (see as an example,
Ind2 above).

A few utility functions to manipulate GenePop records are made
available, here is an example:

.. code:: python

   from Bio.PopGen import GenePop

   # Imagine that you have loaded rec, as per the code snippet above...

   rec.remove_population(pos)
   # Removes a population from a record, pos is the population position in
   # rec.populations, remember that it starts on position 0.
   # rec is altered.

   rec.remove_locus_by_position(pos)
   # Removes a locus by its position, pos is the locus position in
   #  rec.loci_list, remember that it starts on position 0.
   #  rec is altered.

   rec.remove_locus_by_name(name)
   # Removes a locus by its name, name is the locus name as in
   # rec.loci_list. If the name doesn't exist the function fails
   # silently.
   # rec is altered.

   rec_loci = rec.split_in_loci()
   # Splits a record in loci, that is, for each loci, it creates a new
   # record, with a single loci and all populations.
   # The result is returned in a dictionary, being each key the locus name.
   # The value is the GenePop record.
   # rec is not altered.

   rec_pops = rec.split_in_pops(pop_names)
   # Splits a record in populations, that is, for each population, it creates
   # a new record, with a single population and all loci.
   # The result is returned in a dictionary, being each key
   # the population name. As population names are not available in GenePop,
   # they are passed in array (pop_names).
   # The value of each dictionary entry is the GenePop record.
   # rec is not altered.

GenePop does not support population names, a limitation which can be
cumbersome at times. Functionality to enable population names is
currently being planned for Biopython. These extensions won’t break
compatibility in any way with the standard format. In the medium term,
we would also like to support the GenePop web service.
