def __init__(self, fit_fun='pgg', inst=None, mutationBoundaries=True):

        logging.basicConfig(level=logging.INFO,
                            format='[%(asctime)s]::%(levelname)s  %(message)s',
                            datefmt='%Y.%m.%d - %H:%M:%S')

        logging.info('Creating population')

        if inst is None:
            self.pathToInputFiles = PARAMETER_FOLDER
            self.pathToOutputFiles = OUTPUT_FOLDER
        else:
            self.pathToInputFiles = inst
            self.pathToOutputFiles = inst

        self.pathToInitFile = fman.getPathToFile(filename=INITIALISATION_FILE,
                                                 dirname=self.pathToInputFiles)
        self.attrs = fman.extractColumnFromFile(self.pathToInitFile, 0, str)
        self.vals = fman.extractColumnFromFile(self.pathToInitFile, 1, int)

        for attr, val in zip(self.attrs, self.vals):
            setattr(self, attr, val)

        self.pathToPhenFile = fman.getPathToFile(
            filename=INITIAL_PHENOTYPES_FILE, dirname=self.pathToInputFiles)
        with open(self.pathToPhenFile) as f:
            self.initialPhenotypes = [float(line) for line in f.readlines()]

        self.pathToTechFile = fman.getPathToFile(
            filename=INITIAL_TECHNOLOGY_FILE, dirname=self.pathToInputFiles)
        self.initialTechnologyLevel = fman.extractColumnFromFile(
            self.pathToTechFile, 0, float)[0]

        self.pathToParFile = fman.getPathToFile(filename=PARAMETER_FILE,
                                                dirname=self.pathToInputFiles)
        self.parattrs = fman.extractColumnFromFile(self.pathToParFile, 0, str)
        self.parvals = fman.extractColumnFromFile(self.pathToParFile, 1, float)

        for parattr, parval in zip(self.parattrs, self.parvals):
            setattr(self, parattr, parval)

        self.pathToFitFile = fman.getPathToFile(
            filename=FITNESS_PARAMETERS_FILE, dirname=self.pathToInputFiles)
        self.fitattrs = fman.extractColumnFromFile(self.pathToFitFile, 0, str)
        self.fitvals = fman.extractColumnFromFile(self.pathToFitFile, 1, float)

        self.fitnessParameters = {}
        for fitattr, fitval in zip(self.fitattrs, self.fitvals):
            self.fitnessParameters[fitattr] = fitval

        if hasattr(self, "individualBaseResources") == False:
            setattr(self, "individualBaseResources", 1)

        self.fit_fun = fit_fun
        self.mutationBoundaries = mutationBoundaries
 def test_initial_phenotypes_format(self):
     self.pathToFile = fman.getPathToFile(filename=INITIAL_PHENOTYPES_FILE,
                                          dirname='test/test')
     with open(self.pathToFile) as f:
         lines = [float(x) for x in f.readlines()]
         for line in lines:
             assert type(line) is float
             assert 0 <= line <= 1
    def test_initialisation_values_provided(self):
        self.pathToFile = fman.getPathToFile(filename=INITIALISATION_FILE,
                                             dirname='test/test')

        self.pars = fman.extractColumnFromFile(self.pathToFile, 1, int)
        for par in self.pars:
            assert type(
                par
            ) is int, "Did you insert a non integer value for deme number, deme size or generation number?"
            assert par > 0, "Did you insert a negative value for deme number, deme size or generation number?"
    def test_population_is_initialised_with_right_values(
            self, objectAttributesExist, objectAttributesValues):
        # First, the population is initialised according to the initialisation settings
        self.pathToFile = fman.getPathToFile(filename=INITIALISATION_FILE,
                                             dirname='test/test')
        self.attributeNames = fman.extractColumnFromFile(
            self.pathToFile, 0, str)
        self.attributeValues = fman.extractColumnFromFile(
            self.pathToFile, 1, int)
        self.population = Pop(inst='test/test')

        testAttr, whichAttr = objectAttributesExist(self.population,
                                                    self.attributeNames)
        assert testAttr, "Population does not have attribute(s) {0}".format(
            whichAttr)
        testVal, attributes, expected, observed = objectAttributesValues(
            self.population, self.attributeNames, self.attributeValues)
        assert testVal, "Population has {1}={2} instead of {3}".format(
            attributes, expected, observed)
    def runSimulation(self):

        if self.numberOfDemes >= 2 and self.fit_fun in fitness.functions:
            self.createAndPopulateDemes()

            self.pathToOutputFolder = fman.getPathToFile(
                self.pathToOutputFiles)
            if not os.path.exists(self.pathToOutputFolder):
                os.makedirs(self.pathToOutputFolder, exist_ok=True)

            phenotypesfile = self.pathToOutputFolder + '/out_phenotypes.txt'
            demographyfile = self.pathToOutputFolder + '/out_demography.txt'
            technologyfile = self.pathToOutputFolder + '/out_technology.txt'
            resourcesfile = self.pathToOutputFolder + '/out_resources.txt'
            consensusfile = self.pathToOutputFolder + '/out_consensus.txt'

            with open(phenotypesfile, "w", buffering=1) as fp, \
            open(demographyfile, "w", buffering=1) as fd, \
            open(technologyfile, "w", buffering=1) as ft, \
            open(resourcesfile, "w", buffering=1) as fr, \
            open(consensusfile, "w", buffering=1) as fc:
                for gen in range(self.numberOfGenerations):
                    logging.info('Running generation {0}'.format(gen))

                    self.lifecycle()

                    if self.demography == 0:
                        #raise ValueError("The population went extinct after {0} generations".format(gen))
                        logging.info(
                            'Population went extinct after {0} generations'.
                            format(gen))
                        phenmeans = [None] * self.numberOfPhenotypes
                        break
                    else:
                        phenmeans = []
                        phenvars = []

                        for phen in range(self.numberOfPhenotypes):
                            tmpPhenotypes = [
                                ind.phenotypicValues[phen]
                                for ind in self.individuals
                            ]
                            tmpMean = ar.specialmean(tmpPhenotypes)
                            tmpVar = ar.specialvariance(
                                sum(tmpPhenotypes),
                                sum(x**2 for x in tmpPhenotypes),
                                len(tmpPhenotypes))

                            phenmeans.append(str(round(tmpMean, 3)))
                            assert type(
                                tmpVar
                            ) is float, "phenotype variance = {0}, phenotypes = {1}".format(
                                tmpVar, tmpPhenotypes)
                            phenvars.append(str(round(tmpVar, 3)))

                        sep = ','
                        fp.write('{0},{1}\n'.format(sep.join(phenmeans),
                                                    sep.join(phenvars)))
                        (demmean, demvar) = ar.extractMeanAndVariance(
                            lst=self.populationStructure, n=self.numberOfDemes)
                        assert all(
                            [x is not None for x in self.advances]
                        ), "some or all deme tech entries are none at generation {1}: {0}".format(
                            self.advances, gen)
                        (techmean, techvar) = ar.extractMeanAndVariance(
                            lst=self.advances, n=self.numberOfDemes)
                        (resmean, resvar) = ar.extractMeanAndVariance(
                            lst=self.resources, n=self.numberOfDemes)
                        assert all(
                            [x is not None for x in self.debatetime]
                        ), "some or all deme debate time entries are none at generation {1}: {0}".format(
                            self.debatetime, gen)
                        (consmean, consvar) = ar.extractMeanAndVariance(
                            lst=self.debatetime, n=self.numberOfDemes)
                        fd.write('{0},{1}\n'.format(demmean, demvar))
                        ft.write('{0},{1}\n'.format(techmean, techvar))
                        fr.write('{0},{1}\n'.format(resmean, resvar))
                        fc.write('{0},{1}\n'.format(consmean, consvar))

        elif self.numberOfDemes < 2 and self.fit_fun in fitness.functions:
            raise ValueError(
                'This program runs simulations on well-mixed populations only. "numberOfDemes" in initialisation.txt must be > 1'
            )

        elif self.numberOfDemes >= 2 and self.fit_fun not in fitness.functions:
            raise KeyError(
                str('Fitness function "{0}" unknown. Add it to the functions in fitness.py'
                    ).format(self.fit_fun))

        else:
            raise ValueError(
                'This program runs simulations on well-mixed populations only. "numberOfDemes" in initialisation.txt must be > 1'
            )
            raise KeyError(
                'Fitness function "{0}" unknown. Add it to the functions in fitness.py'
                .format(self.fit_fun))
 def test_initialisation_parameters_listed(self):
     self.pathToFile = fman.getPathToFile(filename=INITIALISATION_FILE,
                                          dirname='test/test')
     for par in ['numberOfDemes', 'initialDemeSize', 'numberOfGenerations']:
         fman.searchFile(self.pathToFile, par)